2 /*---------------------------------------------------------------------------*/
6 /* Copyright (c) 1995, Cygnus Support */
7 /*---------------------------------------------------------------------------*/
10 #define DEBUG (1) /* Just for testing */
13 /* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
14 build. It is not currently used by the MIPS simulator world
17 /* All output sent to stdout is for the simulator engine. All program
18 related warnings and errors should be sent to stderr. */
20 /* The simulator decode table is constructed this way to allow the
21 minimal code required for a particular instruction type to be
22 coded. This avoids a large simulator source file, with lots of
23 build-time conditionals controlling what code is included. However
24 this two-stage process does mean that care must be taken to ensure
25 that the correct decoding source is generated for a particular MIPS
30 We could provide pipeline modelling by splitting the simulation of
31 instructions into seperate bytecodes for each pipeline
32 stage. e.g. for the VR4300 each instruction would generate 5
33 bytecodes, one for each pipeline stage. The simulator control would
34 then insert these into the relevant pipeline slots, and execute a
35 complete slots worth of bytecodes. However, the shape of the
36 pipeline, and what parts of each instruction are executed in each
37 pipeline stage, are different between MIPS implementations. If we
38 were to construct a simulator for a particular MIPS architecture
39 this would be a good solution.
41 To avoid having to provide multiple different pipeline models, a
42 simple approach for dealing with the delay slots, and register
43 dependencies has been used. The "MIPS IV Instruction Set" document
44 (Revision 3.1 - January 1995) details the standard MIPS instruction
45 set, and it defines operations in instruction (not pipe-line)
46 cycles. This means we only need to worry about a few cases where
47 the result is not available until after the next instruction, or
48 where registers in the previous two instruction cycles may be
49 corrupted. The case for corruption only occurs with HI or LO
50 register access, so we can just keep a count within the engine for
51 upto two cycles before marking the register as safe. We then only
52 need to check the safety flag when performing an update that
53 involves the HI or LO register. The only other case is the
54 BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there
55 must be an instruction between the FP CMP and the BC1[FT]. We can
56 perform the same instruction cycle count scheme, so we can raise a
57 warning if an attempt is made to access the condition code early
58 (NOTE: The hardware does not interlock on this operation, so the
59 simulator should just raise a warning).
61 For the situations where a result is not available until later, we
62 implent a slot to hold pending values. After the PC is incremented,
63 and before the instruction is decoded we can execute the required
64 register update (or remainder of instruction processing). */
66 /* The FP instruction decoding is also provided by this code. The
67 instructions are marked as "FP" ones so that we can construct a
68 simulator without an FPU if required. Similarly we mark
69 instructions as Single or Double precision, since some MIPS
70 processors only have single precision FP hardware. */
72 /* NOTE: Ideally all state should be passed as parameters. This allows
73 a single simulator engine to be used for multiple concurrent
74 simulations. More importantly, if a suitably powerful control is in
75 place it will allow speculative simulation, since the context can
76 be saved easily, and then restored after performing some
77 simulation. The down-side is that for certain host architectures it
78 can slow the simulator down (e.g. if globals can be accessed faster
79 than local structures). However, this is not actually the case at
80 the moment. The constructed engine uses direct names (that can be
81 macro definitions). This keeps the engine source smalled (using
82 short-hands), and it also allows the user to control whether they
83 want to use global, or indirected memory locations. i.e. whether
84 they want a single- or multi-threaded simulator engine. */
86 /* The constructed simulator engine contains manifests for each of the
87 features supported. The code that includes the engine can then
88 discover the available features during its build. This information
89 can be used to control run-time features provided by the final
92 /*---------------------------------------------------------------------------*/
94 /* Program defaults */
96 #define DEF_PROC64 (1 == 1)
97 #define DEF_FP (1 == 1)
98 #define DEF_FPSINGLE (1 == 0)
100 #define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */
101 #define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */
102 #define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */
103 #define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */
104 #define FEATURE_FP64 (1 << 3) /* 0 = FPRLEN 32; 1 = FPRLEN 64 (only used if FEATURE_HASFPU defined */
105 #define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */
106 #define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */
107 #define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */
108 #define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */
109 #define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
110 #define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
111 #define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
113 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
115 /* FEATURE_WARN_STALL */
116 /* If MIPS I we want to raise a warning if an attempt is made to
117 access Rn in an instruction immediately following an Rn update
118 "WARNING : Invalid value read". The simulator engine is designed
119 that the previous value is read in such cases, to allow programs
120 that make use of this feature to execute. *
121 /* If MIPS II or later, attempting to read a register before the
122 update has completed will generate a "WARNING : Processor stall"
123 message (since the processor will lock the pipeline until the value
124 becomes available). */
126 /* FEATURE_WARN_LOHI */
127 /* Warn if an attempt is made to read the HI/LO registers before the
128 update has completed, or if an attempt is made to update the
129 registers whilst an update is occurring. */
131 /* FEATURE_WARN_ZERO */
132 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
134 /* FEATURE_WARN_R31 */
135 /* Notify the user if register r31 (the default procedure call return
136 address) is used unwisely. e.g. If r31 is used as the source in a
137 branch-and-link instruction, it would mean that an exception in the
138 delay slot instruction would not allow the branch to be re-started
139 (since r31 will have been overwritten by the link operation during
140 the first execution of the branch). */
142 /* FEATURE_WARN_RESULT */
143 /* Certain instructions do not raise exceptions when invalid operands
144 are given, they will just result in undefined values being
145 generated. This option controls whether the simulator flags such
148 /*---------------------------------------------------------------------------*/
154 #include "opcode/mips.h" /* From Cygnus progressive tree */
156 /* The following manifests do not appear in "progressive/include/opcode/mips.h" */
157 #define OP_SH_LOCC (8) /* FP condition code */
158 #define OP_SH_HICC (18) /* FP condition code */
159 #define OP_MASK_CC (0x07)
160 #define OP_SH_CC (8) /* FP condition code */
161 #define OP_MASK_CC (0x07)
162 #define OP_SH_FORMAT (21) /* FP short format field */
163 #define OP_MASK_FORMAT (0x07)
164 #define OP_SH_TRUE (16)
165 #define OP_MASK_TRUE (0x01)
166 #define OP_SH_GE (17)
167 #define OP_MASK_GE (0x01)
168 #define OP_SH_UNSIGNED (16)
169 #define OP_MASK_UNSIGNED (0x01)
170 #define OP_SH_HINT (16)
171 #define OP_MASK_HINT (0x1F)
174 #define TRUE (1 == 1)
175 #define FALSE (1 == 0)
178 /*---------------------------------------------------------------------------*/
180 /* Holding the instruction table this way makes it easier to check the
181 instruction values defined, and to add instructions to the
182 system. However, it makes the process of constructing the simulator
183 a bit more complicated: */
185 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
186 alphabetic characters should be used, since the letter ordinal is
187 used as a bit position): */
189 typedef struct operand_encoding
{
190 char id
; /* character identifier */
191 int fpos
; /* first bit position */
192 int flen
; /* field length in bits */
198 /* Values for the "flags" field: */
199 #define OP_NONE (0 << 0) /* To keep the source tidy */
200 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
201 #define OP_FGR (1 << 1) /* Get operand from FP register bank */
202 #define OP_SIGNX (1 << 2) /* Sign-extend the operand */
203 #define OP_SHIFT2 (1 << 3) /* Shift field left by 2 */
204 #define OP_BITS5 (1 << 4) /* Only take the lo 5-bits of the operand */
206 struct operand_encoding opfields
[] = {
207 {'0',-1,-1,"" ,"" ,(OP_NONE
)}, /* special case for explicit zero */
208 {'1',-1,-1,"" ,"" ,(OP_NONE
)}, /* special case for explicit one */
209 {'?',-1,-1,"" ,"" ,(OP_NONE
)}, /* undefined (do not care at this level) */
210 /* The rest are the explicit operand fields: */
211 {'a', 6, 5,"int" ,"op1" ,(OP_NONE
)}, /* shift amount (or hint) */
212 {'b',21, 5,"t_fpreg","base" ,(OP_FGR
)}, /* FP base/fr register */
213 {'c',16, 1,"int" ,"boolean" ,(OP_NONE
)}, /* TRUE or FALSE boolean */
214 {'d',11, 5,"int" ,"destreg" ,(OP_NONE
)}, /* integer destination/rd register */
215 {'e', 0,16,"t_reg" ,"offset" ,(OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
216 {'f',25, 1,"int" ,"add" ,(OP_NONE
)}, /* TRUE if ADD instruction, FALSE if move or branch */
217 {'g',16, 5,"t_reg" ,"op2" ,(OP_GPR
)}, /* integer source rt register */
218 {'h', 0,16,"t_reg" ,"offset" ,(OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
219 {'i', 0,16,"t_reg" ,"op2" ,(OP_SIGNX
)}, /* signed immediate (op2) */
220 {'j', 0,26,"ut_reg" ,"op1" ,(OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
221 {'k',16, 5,"t_fpreg","index" ,(OP_FGR
)}, /* FP index register */
222 {'l', 0,16,"t_reg" ,"offset" ,(OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
223 {'m',21, 3,"int" ,"format" ,(OP_NONE
)}, /* FP format field */
224 {'n',16, 5,"int" ,"hint" ,(OP_NONE
)}, /* hint */
225 {'o',21, 5,"t_reg" ,"op1" ,(OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
226 {'p', 8, 3,"int" ,"condition_code",(OP_NONE
)}, /* FP condition code field */
227 {'q',18, 3,"int" ,"condition_code",(OP_NONE
)}, /* FP condition code field */
228 {'r', 6, 5,"int" ,"destreg" ,(OP_NONE
)}, /* FP fd register */
229 {'s',21, 5,"t_reg" ,"op1" ,(OP_GPR
)}, /* integer source/rs register */
230 {'t',16, 5,"int" ,"destreg" ,(OP_NONE
)}, /* integer target rt (destination) register */
231 {'u', 0, 4,"int" ,"cmpflags" ,(OP_NONE
)}, /* FP comparison control flags */
232 {'v',11, 5,"t_fpreg","op1" ,(OP_FGR
)}, /* FP fs register or hint */
233 {'w', 0,16,"t_reg" ,"offset" ,(OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
234 {'x',24, 1,"int" ,"branch" ,(OP_NONE
)}, /* TRUE if branch instruction - FALSE if move or add */
235 {'y', 0,16,"t_reg" ,"offset" ,(OP_SIGNX
)}, /* signed offset */
236 {'z', 0,16,"ut_reg" ,"op2" ,(OP_NONE
)}, /* unsigned immediate (zero extended) */
239 /* Main instruction encoding types: */
249 /* Main instruction families: */
251 ADD
, /* res = operand1 + operand2 */
252 SUB
, /* res = operand1 - operand2 */
253 MUL
, /* res = operand1 * operand2 */
254 DIV
, /* res = operand1 / operand2 */
255 AND
, /* res = operand1 & operand2 */
256 OR
, /* res = operand1 | operand2 */
257 XOR
, /* res = operand1 ^ operand2 */
258 MOVE
, /* res = operand1 */
259 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
260 JUMP
, /* execute delay slot instruction before jump */
261 LOAD
, /* load from memory */
262 STORE
, /* store to memory */
263 PREFETCH
, /* prefetch data into cache */
264 SET
, /* set register on result of condition code */
265 SHIFT
, /* perform a logical or arithmetic shift */
266 TRAP
, /* system exception generation */
267 BREAK
, /* system breakpoint exception generation */
268 SYSCALL
, /* system exception generation */
269 SYNC
, /* system cache control */
270 DECODE
, /* co-processor instruction */
271 CACHE
, /* co-processor 0 CACHE instruction */
272 MADD16
, /* VR4100 specific multiply-add extensions */
284 FPMAB
, /* Special encoding for MOVE, ADD and BRANCH instructions */
292 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
296 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
297 #define SIM_SH_SIZE (0)
298 #define SIM_MASK_SIZE (0x3)
302 #define DOUBLEWORD (3)
304 /* Shorthand to get the size field from the flags value: */
305 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
307 /* The rest are single bit flags: */
308 #define COPROC (1 << 2)
309 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
314 #define LIKELY (1 << 8)
315 #define SIGNEXTEND (1 << 9)
316 #define OVERFLOW (1 << 10)
317 #define LINK (1 << 11)
318 #define ATOMIC (1 << 12)
319 #define SHIFT16 (1 << 13)
320 #define REG (1 << 14)
321 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
322 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
323 #define LOGICAL (1 << 17)
324 #define ARITHMETIC (1 << 18)
325 #define UNSIGNED (1 << 19)
326 #define HI32 (1 << 20)
327 #define HI (1 << 21) /* accesses or updates the HI register */
328 #define LO (1 << 22) /* accesses or updates the LO register */
329 #define WORD32 (1 << 23)
330 #define FP (1 << 24) /* Floating Point operation */
331 #define FIXED (1 << 25) /* fixed point arithmetic */
332 #define SINGLE (1 << 26) /* single precision FP */
333 #define DOUBLE (1 << 27) /* double precision FP */
334 /**** Bits 28, 29 and 30 available ****/
335 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
337 typedef struct instruction
{
338 char *name
; /* ASCII mnemonic name */
339 unsigned int isa
; /* MIPS ISA number where instruction introduced */
340 char *bitmap
; /* 32character string describing instruction operands */
341 inst_type mark
; /* type of MIPS instruction encoding */
342 opcode_type type
; /* main instruction family */
343 unsigned int flags
; /* flags describing instruction features */
345 /* The number of pipeline cycles taken by an instruction varies
346 between MIPS processors. This means that the information must be
347 encoded elsewhere, in a CPU specific structure. */
349 /* NOTE: Undefined instructions cause "Reserved Instruction"
350 exceptions. i.e. if there is no bit-mapping defined then the
351 instruction is deemed to be undefined. */
353 /* NOTE: The "isa" field is also used to encode flags for particular
354 chip architecture extensions. e.g. the NEC VR4100 specific
355 instructions. Normally chip extensions are added via the COP0
356 space. However, the VR4100 (and possibly other devices) also use
357 the normal instruction space. */
358 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
359 /* The other bits are allocated downwards, to avoid renumbering if we
360 have to extend the bits allocated to the pure ISA number. */
361 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
363 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
364 COP0 space. This means that an external decoder should be added
365 when constructing a full VR4100 simulator. However some arithmetic
366 instructions are encoded in the normal instruction space. */
368 struct instruction MIPS_DECODE
[] = {
369 /* The instructions are alphabetical, and not in instruction bit-order: */
370 {"ABS", 1,"01000110mmm00000dddddaaaaa000101",COP1
, FPABS
, (FP
)},
371 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
372 {"%s", 1,"010001fxmmmnnnnndddddaaaaa000000",COP1
, FPMAB
, (FP
)},
373 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
374 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
375 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
376 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
377 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
378 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
379 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
380 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
381 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
382 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
383 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
384 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
385 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
386 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
387 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
388 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
389 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
390 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
391 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
392 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
393 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
394 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
395 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
396 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
397 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
398 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
399 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
400 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
401 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
402 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
403 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
404 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
405 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
406 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
407 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
408 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
409 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
410 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
411 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
412 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
413 {"DMADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
414 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
415 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
416 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
417 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
418 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
419 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
420 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
421 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
422 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
423 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
424 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
425 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
426 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
427 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
428 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
429 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
430 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
431 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
432 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
433 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
434 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
435 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
436 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
437 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
438 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
439 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
440 {"LDXC1", 4,"010011bbbbbkkkkk00000rrrrr000001",COP1X
, FPLOAD
, (FP
| DOUBLEWORD
)},
441 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
442 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
443 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
444 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
445 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
446 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
447 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
448 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
449 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
450 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
451 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
452 {"LWXC1", 4,"010011bbbbbkkkkk00000rrrrr000000",COP1X
, FPLOAD
, (FP
| WORD
)},
453 {"MADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
454 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
455 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
456 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
)}, /* with following, from and to denoted by usage of "s" or "d" */
457 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
)},
458 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
)},
459 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
)},
460 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
461 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
462 {"MOVN", 4,"01000110mmmkkkkkvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
)},
463 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
)}, /* Test FP condition code, and conditionally move integer register */
464 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
)}, /* to test an FP condition and conditionally move an FP value */
465 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
466 {"MOVZ", 4,"01000110mmmkkkkkvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
)},
467 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
468 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
469 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
470 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
471 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
472 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
| FIXED
| DOUBLEWORD
)},
473 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
474 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
475 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
476 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
477 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
478 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
479 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
480 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
481 {"PREFX", 4,"010011bbbbbkkkkkvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
482 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
483 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
484 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
485 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
)},
486 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
487 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
488 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
489 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
490 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
491 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
492 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
493 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
494 {"SDXC1", 4,"010011bbbbbkkkkkvvvvv00000001001",COP1X
, FPSTORE
, (FP
| DOUBLEWORD
)},
495 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
496 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
497 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
498 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
499 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
500 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
501 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
502 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
503 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| WORD
| RIGHT
| ARITHMETIC
)},
504 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| WORD
| RIGHT
| ARITHMETIC
)},
505 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| WORD
| RIGHT
| LOGICAL
)},
506 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| WORD
| RIGHT
| LOGICAL
)},
507 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
508 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
509 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
510 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
511 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
512 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
513 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
514 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
515 {"SWXC1", 4,"010011bbbbbkkkkkvvvvv00000001000",COP1X
, FPSTORE
, (FP
)},
516 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
517 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
518 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
519 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
520 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
521 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
522 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
523 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
524 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
525 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
526 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
527 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
528 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
529 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
530 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
531 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
532 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
533 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
534 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
535 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
538 /*---------------------------------------------------------------------------*/
540 /* We use the letter ordinal as the bit-position in our flags field: */
541 #define fieldval(l) (1 << ((l) - 'a'))
544 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
546 unsigned int *onemask
, *zeromask
, *dontmask
;
548 unsigned int flags
= 0x00000000;
549 int loop
; /* current bitmap position */
550 int lastsp
= -1; /* last bitmap field starting position */
551 int lastoe
= -1; /* last bitmap field encoding */
553 *onemask
= 0x00000000;
554 *zeromask
= 0x00000000;
555 *dontmask
= 0x00000000;
557 if (strlen(bitmap
) != 32) {
558 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
562 for (loop
= 0; (loop
< 32); loop
++) {
564 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
565 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
567 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
568 if ((lastoe
!= -1) && (lastoe
!= oefield
))
569 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
570 fprintf(stderr
,"Invalid field length %d for bitmap field '%c' (0x%02X) (should be %d)\n",(loop
- lastsp
),(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],opfields
[lastoe
].flen
);
574 switch (bitmap
[31 - loop
]) {
575 case '0' : /* fixed value */
576 *zeromask
|= (1 << loop
);
581 case '1' : /* fixed value */
582 *onemask
|= (1 << loop
);
587 case '?' : /* fixed value */
588 *dontmask
|= (1 << loop
);
593 default : /* check character encoding */
595 if (opfields
[oefield
].fpos
!= -1) {
596 /* If flag not set, then check starting position: */
597 if (!(flags
& fieldval(bitmap
[31 - loop
]))) {
598 if (loop
!= opfields
[oefield
].fpos
) {
599 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
);
602 flags
|= fieldval(bitmap
[31 - loop
]);
607 *dontmask
|= (1 << loop
);
612 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
);
617 /* NOTE: Since we check for the position and size of fields when
618 parsing the "bitmap" above, we do *NOT* need to check that invalid
619 field combinations have been used. */
624 /*---------------------------------------------------------------------------*/
627 build_operands(flags
)
631 for (loop
= 0; (loop
< (sizeof(opfields
) / sizeof(operand_encoding
))); loop
++)
632 if ((opfields
[loop
].fpos
!= -1) && (flags
& fieldval(opfields
[loop
].id
))) {
633 printf(" %s %s = ",opfields
[loop
].type
,opfields
[loop
].name
);
635 if (opfields
[loop
].flags
& OP_SIGNX
)
636 printf("SIGNEXTEND((%s)",opfields
[loop
].type
);
638 if (opfields
[loop
].flags
& (OP_GPR
| OP_FGR
))
639 printf("%s[",((opfields
[loop
].flags
& OP_GPR
) ? "GPR" : "FGR"));
641 if (opfields
[loop
].flags
& OP_SHIFT2
)
644 printf("((instruction >> %d) & 0x%08X)",opfields
[loop
].fpos
,((1 << opfields
[loop
].flen
) - 1));
646 if (opfields
[loop
].flags
& OP_SHIFT2
)
649 if (opfields
[loop
].flags
& (OP_GPR
| OP_FGR
))
652 if (opfields
[loop
].flags
& OP_BITS5
)
655 if (opfields
[loop
].flags
& OP_SIGNX
)
656 printf(",%d)",(opfields
[loop
].flen
+ ((opfields
[loop
].flags
& OP_SHIFT2
) ? 2 : 0)));
664 /*---------------------------------------------------------------------------*/
665 /* doisa = number of MIPS ISA simulator table is being constructed for.
666 * proc64 = TRUE if constructing 64bit processor world.
667 * dofp = boolean, TRUE if FP instructions are to be included.
668 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
672 process_instructions(doarch
,features
)
674 unsigned int features
;
676 int doisa
= (doarch
& MASK_ISA
);
677 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
678 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
679 int fprlen
=((features
& FEATURE_FP64
) ? 64 : 32);
680 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
681 int dofp
= (features
& FEATURE_HASFPU
);
682 int fpsingle
= (features
& FEATURE_FPSINGLE
);
686 fprintf(stderr
,"process_instructions: invalid structure length\n");
690 if (proc64
&& (gprlen
!= 64)) {
691 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
695 fprlen
= ((features
& FEATURE_FP64
) ? 64 : 32);
696 if (fprlen
!= gprlen
)
697 fprintf(stderr
,"Warning: FPR (%d) and GPR (%d) are different sizes\n",fprlen
,gprlen
);
699 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
701 printf("#if defined(SIM_MANIFESTS)\n");
703 printf("#define PROCESSOR_64BIT (1 == 1)\n");
704 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
705 printf("#define GPRLEN (%d)\n",gprlen
);
706 printf("#define FPRLEN (%d)\n",fprlen
);
707 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
708 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
709 printf("typedef %s t_fpreg;\n",((fprlen
== 64) ? "word64" : "int"));
711 printf("#define HASFPU (1 == 1)\n");
712 if (features
& FEATURE_FAST
)
713 printf("#define FASTSIM (1 == 1)\n");
714 if (features
& FEATURE_WARN_STALL
)
715 printf("#define WARN_STALL (1 == 1)\n");
716 if (features
& FEATURE_WARN_LOHI
)
717 printf("#define WARN_LOHI (1 == 1)\n");
718 if (features
& FEATURE_WARN_ZERO
)
719 printf("#define WARN_ZERO (1 == 1)\n");
720 if (features
& FEATURE_WARN_MEM
)
721 printf("#define WARN_MEM (1 == 1)\n");
722 if (features
& FEATURE_WARN_R31
)
723 printf("#define WARN_R31 (1 == 1)\n");
724 if (features
& FEATURE_WARN_RESULT
)
725 printf("#define WARN_RESULT (1 == 1)\n");
727 printf("#else /* simulator engine */\n");
729 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
730 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
732 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
733 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
736 printf("#if !defined(PROCESSOR_64BIT)\n");
737 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
741 printf("/* Actual instruction decoding block */\n");
743 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
744 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",(OP_MASK_OP
+ 1),OP_SH_SPEC
,OP_MASK_SPEC
);
745 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)),OP_SH_RT
,OP_MASK_RT
);
746 printf("else if (num == 0x11) num = (%d + ((instruction >> %d) & 0x%08X));\n",((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)),OP_SH_SPEC
,OP_MASK_SPEC
);
747 printf("else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)),OP_SH_SPEC
,OP_MASK_SPEC
);
748 printf("/* Total possible switch entries: %d */\n",((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_SPEC
+ 1))) ;
749 printf("switch (num)\n") ;
752 for (loop
= 1; (loop
< limit
); loop
++) {
753 /* First check that the ISA number we are constructing for is
754 valid, before checking if the instruction matches any of the
755 architecture specific flags. NOTE: We allow a selected ISA of
756 zero to be used to match all standard instructions. */
757 if (((((MIPS_DECODE
[loop
].isa
& MASK_ISA
) <= doisa
) || (doisa
== 0)) && (((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
))) {
758 unsigned int onemask
;
759 unsigned int zeromask
;
760 unsigned int dontmask
;
763 unsigned int flags
= convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
764 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
766 if ((GETDATASIZE() == DOUBLEWORD
) && !proc64
) {
767 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
772 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
773 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
774 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
777 switch (MIPS_DECODE
[loop
].mark
) {
779 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
780 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
784 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
785 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
789 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
790 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
794 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
795 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
799 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
800 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
804 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
808 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
811 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
812 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
815 /* Check if there are any other explicit bits in the instruction: */
816 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
817 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
819 printf(" SignalException(ReservedInstruction,instruction);\n") ;
824 if ((flags
== 0) && !(MIPS_DECODE
[loop
].flags
& NOARG
)) {
825 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE
[loop
].name
) ;
831 /* Get hold of the operands */
832 /* NOTE: If we wanted to make the simulator code smaller, we
833 * could pull these into a common sequence before we perform
834 * the instruction decoding. However, this would affect the
835 * performance since unnecessary field extraction would be
836 * occurring for certain instructions.
838 * Also we do not perform checking for multiple definitions of a
839 * particular operand here, since they are caught by the
840 * compilation of the produced code.
842 build_operands(flags
);
844 /* Finish constructing the jump address if required: */
845 if (flags
& fieldval('j'))
846 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
848 /* Now perform required operand checks: */
850 /* The following code has been removed, since it seems perfectly
851 reasonable to have a non-aligned offset that is added to another
852 non-aligned base to create an aligned address. Some more
853 information on exactly what the MIPS IV specification requires is
854 needed before deciding on the best strategy. Experimentation with a
855 VR4300 suggests that we do not need to raise the warning. */
857 /* For MIPS IV (and onwards), certain instruction operand values
858 will give undefined results. For the simulator we could
859 generate explicit exceptions (i.e. ReservedInstruction) to
860 make it easier to spot invalid use. However, for the moment we
861 just raise a warning. NOTE: This is a different check to the
862 later decoding, which checks for the final address being
864 if ((flags
& (fieldval('e') | fieldval('w') | fieldval('h'))) && ((doisa
== 4) || (doisa
== 0))) {
865 printf(" if (instruction & 0x%1X)\n",((flags
& fieldval('e')) ? 0x7 : ((flags
& fieldval('w')) ? 0x3 : 0x1)));
867 /* NOTE: If we change this to a SignalException(), we must
868 ensure that the following opcode processing is not
869 executed. i.e. the code falls straight out to the simulator
871 printf(" WARNING(\"Instruction has lo-order offset bits set in instruction\");\n");
876 /* The extended condition codes only appeared in ISA IV */
877 if ((flags
& fieldval('p')) && ((doisa
< 4) && (doisa
!= 0))) {
878 printf(" if (condition_code != 0)\n");
880 printf(" SignalException(ReservedInstruction,instruction);\n");
885 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && (GETDATASIZE() != WORD
)) {
886 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
890 /* Check that the source is a 32bit value */
891 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) {
892 /* This relies on the compiler optimising out an OR with zero */
893 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
894 printf(" UndefinedResult();\n") ;
900 switch (MIPS_DECODE
[loop
].type
) {
901 /* TODO: To make these easier to edit and maintain, they should
902 actually be provided as source macros (or inline functions)
903 OUTSIDE this main switch statement. */
908 char *basetype
= "unknown";
909 switch (GETDATASIZE()) {
914 basetype
= "long long";
917 fprintf(stderr
,"Opcode table error: size of SUB operands not known (%d)\n",GETDATASIZE());
921 if ((MIPS_DECODE
[loop
].type
) == ADD
) {
922 printf(" unsigned %s temp = (unsigned %s)(op1 + op2);\n",basetype
,basetype
);
923 printf(" signed %s tempS = (signed %s)temp;\n",basetype
,basetype
);
924 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
925 printf(" SignalException(IntegerOverflow);\n");
927 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
928 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
929 else /* only sign-extend when placing 32bit result in 64bit processor */
930 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
932 printf(" unsigned %s temp = (unsigned %s)(op1 - op2);\n",basetype
,basetype
);
933 printf(" signed %s tempS = (signed %s)temp;\n",basetype
,basetype
);
934 if (MIPS_DECODE
[loop
].flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
935 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
936 printf(" SignalException(IntegerOverflow);\n");
939 /* UNSIGNED 32bit operations on a 64bit processor should
940 *STILL* be sign-extended. We have cheated in the
941 data-structure, by not marking it with UNSIGNED, and not
943 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
944 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
945 else /* only sign-extend when placing 32bit result in 64bit processor */
946 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
952 if (features
& FEATURE_WARN_LOHI
) {
953 printf(" CHECKHILO(\"Multiplication\");\n");
956 if (GETDATASIZE() == DOUBLEWORD
) {
957 printf(" uword64 mid;\n");
958 printf(" uword64 temp;\n");
959 printf(" LO = ((op1 & 0xFFFFFFFF) * (op2 & 0xFFFFFFFF));\n");
960 printf(" HI = ((op1 >> 32) * (op2 >> 32));\n");
961 printf(" mid = ((op1 >> 32) * (op2 & 0xFFFFFFFF));\n");
962 printf(" temp = (LO + ((mid & 0xFFFFFFFF) << 32));\n");
963 printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n");
964 printf(" HI += 1;\n");
965 printf(" HI += ((mid >> 32) & 0xFFFFFFFF);\n");
966 printf(" mid = ((op1 & 0xFFFFFFFF) * (op2 >> 32));\n");
967 printf(" LO = (temp + ((mid & 0xFFFFFFFF) << 32));\n");
968 printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n");
969 printf(" HI += 1;\n");
970 printf(" HI += ((mid >> 32) & 0xFFFFFFFF);\n");
972 printf(" uword64 temp = (op1 * op2);\n");
973 printf(" LO = SIGNEXTEND((%s)(temp & 0xFFFFFFFF),32);\n",regtype
);
974 printf(" HI = SIGNEXTEND((%s)((temp >> 32) & 0xFFFFFFFF),32);\n",regtype
);
981 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
983 if (features
& FEATURE_WARN_LOHI
) {
984 printf(" CHECKHILO(\"Division\");\n");
987 if (GETDATASIZE() == DOUBLEWORD
) {
988 printf(" LO = ((%slong long)op1 / (%slong long)op2);\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
989 printf(" HI = ((%slong long)op1 %c (%slong long)op2);\n",(boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
991 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
992 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
1000 int datalen
= GETDATASIZE();
1001 int bits
= ((datalen
== WORD
) ? 32 : 64);
1002 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
1004 /* Check that the specified SHIFT is valid: */
1005 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
1006 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",MIPS_DECODE
[loop
].name
);
1009 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1010 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",MIPS_DECODE
[loop
].name
);
1013 if (!(MIPS_DECODE
[loop
].flags
& LEFT
) && !(MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1014 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",MIPS_DECODE
[loop
].name
);
1017 if ((MIPS_DECODE
[loop
].flags
& LOGICAL
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1018 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1021 if (!(MIPS_DECODE
[loop
].flags
& LOGICAL
) && !(MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1022 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1025 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1026 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",MIPS_DECODE
[loop
].name
);
1030 /* If register specified shift, then extract the relevant shift amount: */
1031 if (flags
& fieldval('s'))
1032 printf(" op1 &= 0x%02X;\n",(bits
- 1));
1034 /* If HI32 specified, then shift range is 32..63 */
1035 if (MIPS_DECODE
[loop
].flags
& HI32
)
1036 printf(" op1 |= (1 << 6);\n");
1038 /* TODO: We should not need to perform the pre-masking with
1039 0xFFFFFFFF when shifting left. The sign-extension code (if
1040 required) will replace any remaining hi-bits. */
1041 printf(" GPR[destreg] = ((unsigned long long)(op2%s) %s op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""),((MIPS_DECODE
[loop
].flags
& LEFT
) ? "<<" : ">>"));
1043 /* For ARITHMETIC shifts, we must duplicate the sign-bit */
1044 if (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)
1045 printf(" GPR[destreg] |= ((op2 & ((%s)1 << %d)) ? ((((%s)1 << (op1 + 1)) - 1) << (%d - op1)) : 0);\n",ltype
,(bits
- 1),ltype
,(bits
- 1));
1047 /* Ensure WORD values are sign-extended into 64bit registers */
1048 if ((bits
== 32) && (gprlen
== 64))
1049 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
1054 if (MIPS_DECODE
[loop
].flags
& (HI
| LO
)) {
1055 char *regname
= ((MIPS_DECODE
[loop
].flags
& LO
) ? "LO" : "HI");
1056 if (flags
& fieldval('d'))
1057 printf(" GPR[destreg] = %s;\n",regname
);
1059 if (features
& FEATURE_WARN_LOHI
) {
1060 printf(" if (%sACCESS != 0)\n",regname
);
1061 printf(" WARNING(\"MT (move-to) over-writing %s register value\");\n",regname
);
1063 printf(" %s = op1;\n",regname
);
1065 if (features
& FEATURE_WARN_LOHI
)
1066 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname
);
1068 if (MIPS_DECODE
[loop
].flags
& SHIFT16
)
1069 printf(" GPR[destreg] = (op2 << 16);\n");
1071 /* perform conditional move */
1072 if (!(MIPS_DECODE
[loop
].flags
& EQ
)) {
1073 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",MIPS_DECODE
[loop
].name
);
1076 printf(" if (op2 %c= 0)\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1077 printf(" GPR[destreg] = op1;\n");
1082 printf(" SyncOperation(op1);\n");
1086 printf(" SignalException(SystemCall);\n");
1090 printf(" SignalException(BreakPoint);\n");
1095 int boolNOT
= (MIPS_DECODE
[loop
].flags
& NOT
);
1096 int boolEQ
= (MIPS_DECODE
[loop
].flags
& EQ
);
1097 int boolGT
= (MIPS_DECODE
[loop
].flags
& GT
);
1098 int boolLT
= (MIPS_DECODE
[loop
].flags
& LT
);
1099 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1101 if (boolGT
&& boolLT
) {
1102 fprintf(stderr
,"GT and LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1106 if (boolNOT
&& (boolGT
|| boolLT
)) {
1107 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1111 printf(" if ((%slong long)op1 ",(boolU
? "unsigned " : ""));
1112 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
1113 printf(" (%slong long)op2)\n",(boolU
? "unsigned " : ""));
1114 printf(" SignalException(Trap);\n");
1120 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1122 if (!(MIPS_DECODE
[loop
].flags
& LT
)) {
1123 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1127 printf(" if ((%slong long)op1 < (%slong long)op2)\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
1128 printf(" GPR[destreg] = 1;\n");
1130 printf(" GPR[destreg] = 0;\n");
1135 printf(" GPR[destreg] = (op1 & op2);\n");
1139 printf(" GPR[destreg] = (%sop1 | op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? "~" : ""));
1143 printf(" GPR[destreg] = (op1 ^ op2);\n");
1147 printf(" decode_coproc(instruction);\n");
1151 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1152 /* The virtual address is translated to a physical address using the TLB */
1153 /* The hint specifies a cache operation for that address */
1154 printf(" uword64 vaddr = (op1 + offset);\n");
1155 printf(" uword64 paddr;\n");
1156 printf(" int uncached;\n");
1157 /* NOTE: We are assuming that the AddressTranslation is a load: */
1158 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1159 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1162 case MADD16
: /* VR4100 specific multiply-add instructions */
1163 /* Some of this code is shared with the standard multiply
1164 routines, so an effort should be made to merge where
1166 if (features
& FEATURE_WARN_LOHI
) {
1167 printf(" CHECKHILO(\"Multiply-Add\");\n");
1169 if (features
& FEATURE_WARN_RESULT
) {
1170 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1171 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1172 printf(" WARNING(\"MADD16 operation with non-16bit operands\");\n");
1175 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1176 if (GETDATASIZE() == DOUBLEWORD
) {
1177 printf(" LO = LO + temp;\n");
1179 printf(" temp += (((HI&0xFFFFFFFF) << 32) | (LO & 0xFFFFFFFF));\n");
1180 printf(" LO = SIGNEXTEND((%s)(temp & 0xFFFFFFFF),32);\n",regtype
);
1181 printf(" HI = SIGNEXTEND((%s)((temp >> 32) & 0xFFFFFFFF),32);\n",regtype
);
1186 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1187 if ((doisa
< 4) && (doisa
!= 0)) {
1188 printf(" if (CoProcPresent(3))\n");
1189 printf(" SignalException(CoProcessorUnusable);\n");
1192 printf(" SignalException(ReservedInstruction,instruction);\n");
1196 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1197 if (!(MIPS_DECODE
[loop
].flags
& REG
))
1198 printf(" int destreg = 31;\n");
1199 printf(" GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */\n");
1202 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1203 printf(" DSPC = op1;\n");
1204 printf(" DELAYSLOT();\n");
1207 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1208 if ((MIPS_DECODE
[loop
].flags
& NOT
) && !(MIPS_DECODE
[loop
].flags
& EQ
)) {
1209 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1212 if ((MIPS_DECODE
[loop
].flags
& NOT
) && (MIPS_DECODE
[loop
].flags
& (GT
| LT
))) {
1213 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1218 if (MIPS_DECODE
[loop
].flags
& GT
)
1219 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1221 if (MIPS_DECODE
[loop
].flags
& LT
)
1222 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1224 if (MIPS_DECODE
[loop
].flags
& EQ
)
1225 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1227 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1228 if (features
& FEATURE_WARN_R31
) {
1229 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
1230 printf(" WARNING(\"Branch with link using r31 as source operand\");\n");
1232 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1235 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1236 printf(" if (condition) {\n");
1237 printf(" DSPC = (PC + offset);\n");
1238 printf(" DELAYSLOT();\n");
1240 if (MIPS_DECODE
[loop
].flags
& LIKELY
) {
1242 printf(" NULLIFY();\n");
1246 /* TODO: After writing the main pass through this memory
1247 transfer block, quite a few bugs were discovered, and fixed
1248 in situ. This code should be gone through and tidied and
1250 case PREFETCH
: /* The beginning is shared with normal load operations */
1254 int isload
= ((MIPS_DECODE
[loop
].type
== LOAD
) || (MIPS_DECODE
[loop
].type
== PREFETCH
));
1256 char *accesslength
= "<UNKNOWN>";
1258 switch (GETDATASIZE()) {
1261 accesslength
= "AccessLength_BYTE";
1266 accesslength
= "AccessLength_HALFWORD";
1271 accesslength
= "AccessLength_WORD";
1276 accesslength
= "AccessLength_DOUBLEWORD";
1280 printf(" uword64 vaddr = ((unsigned long long)op1 + offset);\n");
1281 printf(" uword64 paddr;\n");
1282 printf(" int uncached;\n");
1284 /* The following check should only occur on normal (non-shifted) memory loads */
1285 if ((datalen
!= 1) && !(MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
))) {
1286 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
1287 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
1292 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
1294 if (MIPS_DECODE
[loop
].type
== PREFETCH
)
1295 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1298 printf(" %s memval;\n",(proc64
? "uword64" : "unsigned int"));
1300 if (MIPS_DECODE
[loop
].flags
& COPROC
) {
1301 if ((datalen
!= 4) && (datalen
!= 8)) {
1302 fprintf(stderr
,"Co-processor operation not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1307 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
1308 /* NOTE: The R4000 user manual has the COP_LW occuring
1309 in the same cycle as the rest of the instruction,
1310 yet the MIPS IV shows the operation happening on the
1311 next cycle. To keep the simulator simple, this code
1312 follows the R4000 manual. Experimentation with a
1313 silicon implementation will be needed to ascertain
1314 the correct operation. */
1315 printf(" COP_L%c(((instruction >> 26) & 0x3),destreg,memval);\n",((datalen
== 8) ? 'D' : 'W'));
1317 printf(" memval = COP_S%c(((instruction >> 26) & 0x3),destreg);\n",((datalen
== 8) ? 'D' : 'W'));
1318 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength
);
1321 if (MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
)) {
1322 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1323 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1330 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE
[loop
].name
);
1333 /* fall through to... */
1336 char *maskstr
= ((datalen
== 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1338 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
1339 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
1340 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
1341 printf(" int byte;\n");
1342 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
1343 printf(" byte = ((vaddr & mask) ^ bigend);\n");
1344 printf(" if (%sBigEndianMem)\n",((MIPS_DECODE
[loop
].flags
& LEFT
) ? "!" : ""));
1345 printf(" paddr &= ~mask;\n");
1348 if (MIPS_DECODE
[loop
].flags
& LEFT
)
1349 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1351 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
1354 if (MIPS_DECODE
[loop
].flags
& LEFT
) {
1356 /* For WORD transfers work out if the value
1357 will be in the top or bottom of the
1358 DOUBLEWORD returned: */
1359 if (proc64
&& (datalen
== 4)) {
1360 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1361 printf(" memval >>= 32;\n");
1364 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
1365 if (proc64
&& (datalen
== 4))
1366 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1367 } else { /* store */
1368 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
1369 /* TODO: This is duplicated in the LOAD code
1370 above - and the RIGHT LOAD and STORE code
1371 below. It should be merged if possible. */
1372 if (proc64
&& (datalen
== 4)) {
1373 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1374 printf(" memval <<= 32;\n");
1377 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1379 } else { /* RIGHT */
1381 if (proc64
&& (datalen
== 4)) {
1382 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1383 printf(" memval >>= 32;\n");
1387 printf(" uword64 srcmask;\n");
1388 /* All of this extra code is just a bodge
1389 required because some hosts don't allow ((v) << 64).
1390 The SPARC just leaves the (v) value un-touched. */
1391 printf(" if (byte == 0)\n");
1392 printf(" srcmask = 0;\n");
1394 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
1395 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen
);
1397 if (proc64
&& (datalen
== 4))
1398 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1399 } else { /* store */
1400 printf(" memval = (op2 << (byte * 8));\n");
1401 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength
);
1408 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1411 } else { /* normal memory transfer */
1412 if (((datalen
== 8) || ((datalen
== 4) & MIPS_DECODE
[loop
].flags
& UNSIGNED
)) && !proc64
) {
1413 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",MIPS_DECODE
[loop
].name
);
1415 /* TODO: The R4000 documentation suggests the LWU
1416 executed when in 32bit processor mode should cause
1417 a ReservedInstruction exception. This will mean
1418 adding a run-time check into the code sequence. */
1422 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1423 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1424 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1425 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1426 printf(" unsigned int byte;\n");
1428 if (datalen
!= 8) /* not for DOUBLEWORD */
1429 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1431 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
1433 /* The following will only make sense if the "LoadMemory" above returns a DOUBLEWORD entity */
1434 if (datalen
!= 8) { /* not for DOUBLEWORD */
1446 valmask
= 0xFFFFFFFF;
1450 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,MIPS_DECODE
[loop
].name
);
1453 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1454 printf(" GPR[destreg] = ");
1455 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1456 printf("SIGNEXTEND(");
1457 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
1458 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1459 printf(",%d)",(datalen
* 8));
1462 printf(" GPR[destreg] = memval;\n");
1463 } else { /* store operation */
1464 if ((datalen
== 1) || (datalen
== 2)) {
1466 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1467 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1468 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1469 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1470 printf(" unsigned int byte;\n");
1472 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1473 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1474 printf(" memval = (op2 << (8 * byte));\n");
1476 if (proc64
&& (datalen
== 4)) { /* proc64 SC and SW */
1477 printf(" unsigned int byte;\n");
1478 printf(" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (ReverseEndian << 2)));\n");
1479 printf(" byte = ((vaddr & 0x7) ^ (BigEndianCPU << 2));\n");
1480 printf(" memval = (op2 << (8 * byte));\n");
1481 } else /* !proc64 SC and SW, plus proc64 SD and SCD */
1482 printf(" memval = op2;\n");
1484 if (MIPS_DECODE
[loop
].flags
& ATOMIC
)
1485 printf(" if (LLBIT)\n");
1488 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength
);
1492 if (MIPS_DECODE
[loop
].flags
& ATOMIC
) {
1493 if ((datalen
!= 4) && (datalen
!= 8)) {
1494 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",MIPS_DECODE
[loop
].name
);
1498 printf(" LLBIT = 1;\n");
1500 /* The documentation states that:
1502 SC *WILL* fail if coherent store into the same
1503 block occurs, or if an exception occurs between
1504 the LL and SC instructions.
1506 SC *MAY* fail if a load, store or prefetch is
1507 executed on the processor (VR4300 doesn't seem
1508 to), or if the instructions between the LL and
1509 SC are not in a 2048byte contiguous VM range.
1511 SC *MUST* have been preceded by an LL
1512 (i.e. LLBIT will be set), and it must use the
1513 same Vaddr, Paddr and cache-coherence algorithm
1514 as the LL (which means we should store this
1515 information from the load-conditional).
1517 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
1527 /* Following are FP instructions. It may be simpler to provide these
1528 as explicit function calls, rather than coding explicit simulations
1529 at this point. This will help keep this generator simpler, at the
1530 cost of some simulation performance. */
1533 printf(" printf(\"TODO: FPMOVE operation %s */\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1537 MOV%c - integer <-> integer MOVF and MOVT
1538 MOV%c - FP <-> FP MOVF.fmt and MOVT.fmt
1543 printf("/* FPMAB */\n");
1544 printf("if (add) {\n");
1545 printf(" word64 fpop1 = ValueFPR(hint,format);\n");
1546 printf(" word64 fpop2 = ValueFPR(destreg,format);\n");
1547 printf(" StoreFPR(op1,format,(fpop1 + fpop2));\n");
1548 printf("} else if (branch) {\n");
1549 printf(" printf(\"TODO: FP Branch support\\n\");\n");
1550 printf("} else { /* MOVE */\n");
1551 /* TODO: Since the following is so large - maybe it should be punted to a specific routine */
1552 printf(" if ((op1 != 0x0) || (format & (1 << 1)))\n");
1553 printf(" SignalException(ReservedInstruction,instruction);\n");
1556 printf(" int dprec = (format & (1 << 0));\n");
1557 printf(" int to = (format & (1 << 2));\n");
1558 printf(" if (dprec)\n");
1560 printf(" if (to)\n");
1562 if ((doisa
< 4) && (doisa
!= 0))
1564 printf(" if (SizeFGR() == 64)\n");
1565 printf(" FGR[destreg] = GPR[hint];\n");
1567 printf(" if ((destreg & 0x1) == 0)\n");
1569 printf(" FGR[destreg + 1] = (GPR[hint] >> 32);\n");
1570 printf(" FGR[destreg] = (GPR[hint] & 0xFFFFFFFF);\n");
1573 printf(" UndefinedResult();\n");
1577 printf("printf(\"TODO .. pending operation for next cycle\\n\");\n");
1582 if ((doisa
< 4) && (doisa
!= 0))
1584 printf(" if (SizeFGR() == 64)\n");
1585 printf(" GPR[hint] = FGR[destreg];\n");
1587 printf(" if ((destreg & 0x1) == 0)\n");
1588 printf(" GPR[hint] = ((FGR[destreg + 1] << 32) | FGR[destreg]);\n");
1590 printf(" UndefinedResult();\n");
1594 printf(" pending_reg = hint;\n");
1595 printf(" if (SizeFGR() == 64)\n");
1596 printf(" pending_data = FGR[destreg];\n");
1598 printf(" if ((destreg & 0x1) == 0)\n");
1599 printf(" pending_data = ((FGR[destreg + 1] << 32) | FGR[destreg]);\n");
1601 printf(" UndefinedResult();\n");
1605 printf(" else /* single precision */\n");
1607 printf(" if (to)\n");
1609 if ((doisa
< 4) && (doisa
!= 0))
1611 printf(" if (SizeFGR() == 64)\n");
1612 printf(" FGR[destreg] = (0xDEADC0DE | (GPR[hint] & 0xFFFFFFFF));\n");
1614 printf(" FGR[destreg] = (GPR[hint] & 0xFFFFFFFF);\n");
1618 printf(" pending_reg = (FPREG | destreg);\n");
1619 printf(" if (SizeFGR() == 64)\n");
1620 printf(" pending_data = (0xDEADC0DE | (GPR[hint] & 0xFFFFFFFF));\n");
1622 printf(" pending_data = (GPR[hint] & 0xFFFFFFFF);\n");
1626 if ((doisa
==4) || (doisa
== 0)) /* in this cycle */
1628 printf(" GPR[hint] = SIGNEXTEND(FGR[destreg],32);\n");
1630 else /* write-back occurs in next cycle */
1632 printf(" pending_reg = hint;\n");
1633 printf(" pending_data = SIGNEXTEND(FGR[destreg],32);\n");
1641 printf(" printf(\"TODO: FPFLOOR operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1642 /* Lots of checks on paramater validity must be performed */
1646 printf(" printf(\"TODO: FPCEIL operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1650 printf(" printf(\"TODO: FPTRUNC operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1654 printf(" printf(\"TODO: FPROUND operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1658 printf(" printf(\"TODO: FPNEG operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1662 printf(" printf(\"TODO: FPABS operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1666 printf(" printf(\"TODO: FPDIV operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1670 printf(" printf(\"TODO: FPMUL operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1674 printf(" printf(\"TODO: FPSUB operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1678 printf(" printf(\"TODO: FPADD operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1682 printf(" printf(\"TODO: FPPREFX operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1686 printf(" printf(\"TODO: FPSTORE operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1690 printf(" printf(\"TODO: FPLOAD operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1694 printf(" printf(\"TODO: FPRECIP operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1698 printf(" printf(\"TODO: FPSQRT operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1702 printf(" printf(\"TODO: FPCONVERT operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1706 printf(" printf(\"TODO: FPCOMPARE operation %s\\n\");\n",MIPS_DECODE
[loop
].name
) ;
1707 /* "cmpflags" encodes the comparison */
1708 /* if "cmpflags & (1 << 3)" then MIPS IV only */
1709 /* For the MIPS I,II or III there *MUST* be at least one
1710 instruction between the compare that sets a condition code
1711 and the branch that tests it. */
1715 fprintf(stderr
,"Unrecognised opcode type %d\n",MIPS_DECODE
[loop
].type
) ;
1720 printf(" break ;\n") ;
1724 printf("default : /* Unrecognised instruction */\n") ;
1725 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1726 printf(" break ;\n") ;
1728 printf("#endif /* simulator engine */\n");
1733 /*---------------------------------------------------------------------------*/
1735 /* The command-line feature controls are presented in a similar style
1736 to those offered by GCC, in the aim of providing a consistent
1737 interface to the user. */
1739 T_NONE
, /* no argument - mask and value fields control "feature" definition */
1740 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
1741 T_STRING
/* string argument - optionally prcededed by '=' */
1750 } machine_options
[] = {
1751 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
1752 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
1753 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
1754 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
1755 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
1756 {"fp64", T_NONE
, (FEATURE_FP64
| FEATURE_HASFPU
),(FEATURE_FP64
| FEATURE_HASFPU
),"\t\t\tSelect 64bit FP registers"},
1757 {"fp32", T_NONE
, (FEATURE_FP64
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\t\tSelect 32bit FP registers"},
1758 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
1759 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
1763 /* The following architecture identies are those accepted by the "-mcpu" option: */
1764 struct architectures
{
1765 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
1766 unsigned int idflag
; /* or-ed into "isa" value */
1769 static const struct architectures available_architectures
[] = {
1770 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
1771 {0, 0} /* terminator */
1774 /*---------------------------------------------------------------------------*/
1782 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
1785 The output of this program is a block of 'C' code designed to be\n\
1786 included into the main simulation control loop of a device specific\n\
1789 fprintf(stderr
,"\nOptions:\n");
1790 fprintf(stderr
," -h --help\t\tProvide this help text\n");
1791 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
1792 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
1794 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
1795 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
1796 switch (machine_options
[loop
].type
) {
1798 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
1803 fprintf(stderr
,"=name");
1807 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options
[loop
].type
);
1810 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
1813 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
1814 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
1815 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
1816 fprintf(stderr
,"\n\n");
1819 The \"trace\" and \"warnings\" options do not define the output stream.\n\
1820 They only inform the code that includes the constructed engine to provide\n\
1821 the required features.\n\n\
1822 The \"-mips0\" option forces the construction of a simulator supporting\n\
1823 the highest available MIPS ISA supported.\n");
1828 /*---------------------------------------------------------------------------*/
1836 char *progname
= argv
[0];
1837 unsigned int doarch
= DEF_ISA
;
1838 unsigned int features
= 0; /* default state */
1841 features
|= FEATURE_HASFPU
;
1843 features
|= FEATURE_PROC32
;
1845 features
|= FEATURE_FPSINGLE
;
1847 if (features
& FEATURE_PROC32
)
1848 features
&= ~(FEATURE_FP64
| FEATURE_GP64
);
1850 features
|= (FEATURE_FP64
| FEATURE_GP64
);
1853 int this_option_optind
= (optind
? optind
: 1);
1854 int option_index
= 0;
1855 static struct option cmdline
[] = {
1858 {"warnings",0,0,'w'},
1862 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
1864 break ; /* out of the while loop */
1867 case 'h' : /* help */
1871 case 'f' : /* fast */
1872 features
|= FEATURE_FAST
;
1875 case 'w' : /* warnings */
1876 features
|= FEATURE_WARNINGS
;
1877 /* TODO: Future extension: Allow better control over the warnings generated:
1878 disable warnings -wnone ~FEATURE_WARNINGS
1879 all possible warnings -wall FEATURE_WARNINGS
1880 pipeline stall occuring -wstall FEATURE_WARN_STALL
1881 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
1882 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
1883 bad r31 use -wr31 FEATURE_WARN_R31
1884 undefined results -wresult FEATURE_WARN_RESULT
1888 case 'm' : /* machine options */
1892 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
1893 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
1894 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
1895 switch (machine_options
[loop
].type
) {
1898 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
1901 features
&= ~(machine_options
[loop
].mask
);
1902 features
|= machine_options
[loop
].value
;
1906 if (*loptarg
&& *loptarg
== '=')
1909 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
1913 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
1917 num
= strtoul(loptarg
,&loptarg
,10);
1919 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
1920 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
1925 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
1929 if (num
> MASK_ISA
) {
1930 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
1934 doarch
= ((doarch
& ~MASK_ISA
) | num
);
1935 if ((num
== 0) || (num
> 2)) {
1936 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
) || !(features
& FEATURE_FP64
))
1937 fprintf(stderr
,"%s: Warning: -mips%d forcing -mfp64, -mgp64\n",progname
,num
);
1938 features
|= (FEATURE_GP64
| FEATURE_FP64
);
1939 features
&= ~FEATURE_PROC32
;
1941 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
) || (features
& FEATURE_FP64
))
1942 fprintf(stderr
,"%s: Warning: -mips%d forcing -mfp32, -mgp32\n",progname
,num
);
1943 features
&= ~(FEATURE_GP64
| FEATURE_FP64
);
1944 features
|= FEATURE_PROC32
;
1947 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
1953 if (*loptarg
&& *loptarg
== '=')
1956 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
1960 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
1964 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
1965 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
1968 if (*loptarg
&& (*loptarg
== 'r') || (*loptarg
== 'R'))
1971 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
1972 doarch
|= available_architectures
[archloop
].idflag
;
1977 if (available_architectures
[archloop
].name
== 0) {
1978 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
1982 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
1988 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
1994 if (machine_options
[loop
].name
== 0) {
1995 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
2002 /* An error message should already have been displayed */
2006 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
2011 if (optind
< argc
) {
2012 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
2013 while (optind
< argc
)
2014 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
2015 fprintf(stderr
,"\n");
2019 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
2020 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
2022 process_instructions(doarch
,features
) ;
2026 /*---------------------------------------------------------------------------*/
2027 /*> EOF gencode.c <*/