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 /*---------------------------------------------------------------------------*/
169 #include "opcode/mips.h"
171 /* The following manifests do not appear in "include/opcode/mips.h" */
172 #define OP_SH_LOCC (8) /* FP condition code */
173 #define OP_SH_HICC (18) /* FP condition code */
174 #define OP_MASK_CC (0x07)
176 #define OP_SH_COP1NORM (25) /* Normal COP1 encoding */
177 #define OP_MASK_COP1NORM (0x01) /* a single bit */
178 #define OP_SH_COP1SPEC (21) /* Special COP1 encodings (within format field) */
179 #define OP_MASK_COP1SPEC (0x0F) /* Bits we are interested in */
180 #define OP_MASK_COP1SCLR (0x04) /* Bits to be explicitly cleared */
181 #define OP_MASK_COP1CMP (0x3) /* Unfortunately another conditional field needed to decode the FP instructions */
182 #define OP_SH_COP1CMP (4)
184 #define OP_SH_FORMAT (21) /* FP short format field */
185 #define OP_MASK_FORMAT (0x07)
187 #define OP_SH_TRUE (16)
188 #define OP_MASK_TRUE (0x01)
190 #define OP_SH_GE (17)
191 #define OP_MASK_GE (0x01)
193 #define OP_SH_UNSIGNED (16)
194 #define OP_MASK_UNSIGNED (0x01)
196 #define OP_SH_HINT (16)
197 #define OP_MASK_HINT (0x1F)
201 #define TRUE (1 == 1)
202 #define FALSE (1 == 0)
206 /*---------------------------------------------------------------------------*/
208 /* Holding the instruction table this way makes it easier to check the
209 instruction values defined, and to add instructions to the
210 system. However, it makes the process of constructing the simulator
211 a bit more complicated: */
213 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
214 alphabetic characters should be used, since the letter ordinal is
215 used as a bit position): */
217 typedef struct operand_encoding
{
218 char id
; /* character identifier */
219 int fpos
; /* first bit position */
220 int flen
; /* field length in bits */
226 /* Values for the "flags" field: */
227 #define OP_NONE (0 << 0) /* To keep the source tidy */
228 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
229 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
230 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
231 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
233 struct operand_encoding opfields
[] = {
234 {'0',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit zero */
235 {'1',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit one */
236 {'?',-1,-1,"", "", (OP_NONE
)}, /* undefined (do not care at this level) */
237 /* The rest are the explicit operand fields: */
238 {'a', 6, 5,"int", "op1", (OP_NONE
)}, /* shift amount (or hint) */
239 {'b',21, 5,"int", "fr", (OP_NONE
)}, /* fr register */
240 {'c',16, 1,"int", "boolean", (OP_NONE
)}, /* TRUE or FALSE boolean */
241 {'d',11, 5,"int", "destreg", (OP_NONE
)}, /* integer destination/rd register */
242 {'e', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
243 {'f',17, 1,"int", "likely", (OP_NONE
)}, /* set if branch LIKELY */
244 {'g',16, 5,"t_reg", "op2", (OP_GPR
)}, /* integer source rt register */
245 {'h', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
246 {'i', 0,16,"t_reg", "op2", (OP_SIGNX
)}, /* signed immediate (op2) */
247 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
248 {'k',16, 5,"int", "ft", (OP_NONE
)},
249 {'l', 0,16,"t_reg", "offset", (OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
250 {'m',21, 3,"int", "format", (OP_NONE
)}, /* FP format field */
251 {'n',16, 5,"int", "hint", (OP_NONE
)}, /* hint */
252 {'o',21, 5,"t_reg", "op1", (OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
253 {'p', 8, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
254 {'q',18, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
255 {'r', 6, 5,"int", "destreg", (OP_NONE
)}, /* FP fd register */
256 {'s',21, 5,"t_reg", "op1", (OP_GPR
)}, /* integer source/rs register */
257 {'t',16, 5,"int", "destreg", (OP_NONE
)}, /* integer target rt (destination) register */
258 {'u', 0, 4,"int", "cmpflags", (OP_NONE
)}, /* FP comparison control flags */
259 {'v',11, 5,"int", "fs", (OP_NONE
)}, /* FP fs register (or PREFX hint) */
260 {'w', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
261 {'x',23, 1,"int", "to", (OP_NONE
)}, /* TRUE if move To; FALSE if move From */
262 {'y', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset */
263 {'z', 0,16,"ut_reg","op2", (OP_NONE
)}, /* unsigned immediate (zero extended) */
266 /* Main instruction encoding types: */
273 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
277 /* Main instruction families: */
279 ADD
, /* res = operand1 + operand2 */
280 SUB
, /* res = operand1 - operand2 */
281 MUL
, /* res = operand1 * operand2 */
282 DIV
, /* res = operand1 / operand2 */
283 AND
, /* res = operand1 & operand2 */
284 OR
, /* res = operand1 | operand2 */
285 XOR
, /* res = operand1 ^ operand2 */
286 MOVE
, /* res = operand1 */
287 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
288 JUMP
, /* execute delay slot instruction before jump */
289 LOAD
, /* load from memory */
290 STORE
, /* store to memory */
291 PREFETCH
, /* prefetch data into cache */
292 SET
, /* set register on result of condition code */
293 SHIFT
, /* perform a logical or arithmetic shift */
294 TRAP
, /* system exception generation */
295 BREAK
, /* system breakpoint exception generation */
296 SYSCALL
, /* system exception generation */
297 SYNC
, /* system cache control */
298 DECODE
, /* co-processor instruction */
299 CACHE
, /* co-processor 0 CACHE instruction */
300 MADD16
, /* VR4100 specific multiply-add extensions */
318 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
322 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
323 #define SIM_SH_SIZE (0)
324 #define SIM_MASK_SIZE (0x7)
325 #define BYTE (0) /* 8bit */
326 #define HALFWORD (1) /* 16bit */
327 #define WORD (2) /* 32bit */
328 #define DOUBLEWORD (3) /* 64bit */
329 #define SINGLE (4) /* single precision FP */
330 #define DOUBLE (5) /* double precision FP */
332 /* Shorthand to get the size field from the flags value: */
333 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
335 /* The rest are single bit flags: */
336 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
341 #define LIKELY (1 << 8)
342 #define SIGNEXTEND (1 << 9)
343 #define OVERFLOW (1 << 10)
344 #define LINK (1 << 11)
345 #define ATOMIC (1 << 12)
346 #define SHIFT16 (1 << 13)
347 #define REG (1 << 14)
348 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
349 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
350 #define LOGICAL (1 << 17)
351 #define ARITHMETIC (1 << 18)
352 #define UNSIGNED (1 << 19)
353 #define HI32 (1 << 20)
354 #define HI (1 << 21) /* accesses or updates the HI register */
355 #define LO (1 << 22) /* accesses or updates the LO register */
356 #define WORD32 (1 << 23)
357 #define FP (1 << 24) /* Floating Point operation */
358 #define FIXED (1 << 25) /* fixed point arithmetic */
359 #define COPROC (1 << 26)
360 #define INTEGER (1 << 27)
361 #define CONDITIONAL (1 << 28)
362 #define RECIP (1 << 29)
363 #define CONTROL (1 << 30)
364 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
365 /* NOTE: We can overload the use of certain of these flags, since not
366 all options are applicable to all instruction types. This will free
367 up more space for new flags. */
369 typedef struct instruction
{
370 char *name
; /* ASCII mnemonic name */
371 unsigned int isa
; /* MIPS ISA number where instruction introduced */
372 char *bitmap
; /* 32character string describing instruction operands */
373 inst_type mark
; /* type of MIPS instruction encoding */
374 opcode_type type
; /* main instruction family */
375 unsigned int flags
; /* flags describing instruction features */
377 /* The number of pipeline cycles taken by an instruction varies
378 between MIPS processors. This means that the information must be
379 encoded elsewhere, in a CPU specific structure. */
381 /* NOTE: Undefined instructions cause "Reserved Instruction"
382 exceptions. i.e. if there is no bit-mapping defined then the
383 instruction is deemed to be undefined. */
385 /* NOTE: The "isa" field is also used to encode flags for particular
386 chip architecture extensions. e.g. the NEC VR4100 specific
387 instructions. Normally chip extensions are added via the COP0
388 space. However, the VR4100 (and possibly other devices) also use
389 the normal instruction space. */
390 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
391 /* The other bits are allocated downwards, to avoid renumbering if we
392 have to extend the bits allocated to the pure ISA number. */
393 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
395 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
396 COP0 space. This means that an external decoder should be added
397 when constructing a full VR4100 simulator. However some arithmetic
398 instructions are encoded in the normal instruction space. */
400 struct instruction MIPS_DECODE
[] = {
401 /* The instructions are alphabetical, and not in instruction bit-order: */
402 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
403 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
404 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
405 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
406 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
407 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
408 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
409 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
410 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
411 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
412 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
413 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
414 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
415 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
416 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
417 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
418 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
419 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
420 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
421 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
422 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
423 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
424 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
425 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
426 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
427 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
428 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
429 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
430 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
431 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
432 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
433 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
434 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
435 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
436 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
437 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
438 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
439 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
440 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
441 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
442 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
443 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
444 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
445 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
446 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
447 {"DMADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
448 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
449 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
450 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
451 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
452 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
453 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
454 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
455 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
456 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
457 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
458 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
459 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
460 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
461 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
462 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
463 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
464 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
465 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
466 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
467 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
468 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
469 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
470 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
471 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
472 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
473 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
474 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
475 {"LDXC1", 4,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
476 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
477 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
478 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
479 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
480 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
481 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
482 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
483 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
484 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
485 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
486 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
487 {"LWXC1", 4,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
488 {"MADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
489 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
490 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
491 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
)}, /* with following, from and to denoted by usage of "s" or "d" */
492 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
)},
493 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
)},
494 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
)},
495 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
496 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
497 {"MOVN", 4,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
498 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
499 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
500 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
501 {"MOVZ", 4,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
502 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
503 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
504 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
505 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
506 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
507 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
508 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
509 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
510 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
511 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
512 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
513 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
514 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
515 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
516 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
517 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
518 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
519 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
520 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
521 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
522 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
523 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
524 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
525 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
526 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
527 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
528 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
529 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
530 {"SDXC1", 4,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
531 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
532 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
533 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
534 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
535 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
536 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
537 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
538 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
539 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
540 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
541 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
542 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
543 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
544 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
545 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
546 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
547 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
548 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
549 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
550 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
551 {"SWXC1", 4,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
552 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
553 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
554 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
555 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
556 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
557 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
558 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
559 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
560 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
561 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
562 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
563 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
564 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
565 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
566 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
567 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
568 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
569 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
570 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
571 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
574 /*---------------------------------------------------------------------------*/
576 /* We use the letter ordinal as the bit-position in our flags field: */
577 #define fieldval(l) (1 << ((l) - 'a'))
580 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
582 unsigned int *onemask
, *zeromask
, *dontmask
;
584 unsigned int flags
= 0x00000000;
585 int loop
; /* current bitmap position */
586 int lastsp
= -1; /* last bitmap field starting position */
587 int lastoe
= -1; /* last bitmap field encoding */
589 *onemask
= 0x00000000;
590 *zeromask
= 0x00000000;
591 *dontmask
= 0x00000000;
593 if (strlen(bitmap
) != 32) {
594 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
598 for (loop
= 0; (loop
< 32); loop
++) {
600 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
601 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
603 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
604 if ((lastoe
!= -1) && (lastoe
!= oefield
))
605 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
606 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
);
610 switch (bitmap
[31 - loop
]) {
611 case '0' : /* fixed value */
612 *zeromask
|= (1 << loop
);
617 case '1' : /* fixed value */
618 *onemask
|= (1 << loop
);
623 case '?' : /* fixed value */
624 *dontmask
|= (1 << loop
);
629 default : /* check character encoding */
631 if (opfields
[oefield
].fpos
!= -1) {
632 /* If flag not set, then check starting position: */
633 if (!(flags
& fieldval(bitmap
[31 - loop
]))) {
634 if (loop
!= opfields
[oefield
].fpos
) {
635 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
);
638 flags
|= fieldval(bitmap
[31 - loop
]);
643 *dontmask
|= (1 << loop
);
648 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
);
653 /* NOTE: Since we check for the position and size of fields when
654 parsing the "bitmap" above, we do *NOT* need to check that invalid
655 field combinations have been used. */
660 /*---------------------------------------------------------------------------*/
663 build_operands(flags
)
667 for (loop
= 0; (loop
< (sizeof(opfields
) / sizeof(operand_encoding
))); loop
++)
668 if ((opfields
[loop
].fpos
!= -1) && (flags
& fieldval(opfields
[loop
].id
))) {
669 printf(" %s %s = ",opfields
[loop
].type
,opfields
[loop
].name
);
671 if (opfields
[loop
].flags
& OP_SIGNX
)
672 printf("SIGNEXTEND((%s)",opfields
[loop
].type
);
674 if (opfields
[loop
].flags
& OP_GPR
)
677 if (opfields
[loop
].flags
& OP_SHIFT2
)
680 printf("((instruction >> %d) & 0x%08X)",opfields
[loop
].fpos
,((1 << opfields
[loop
].flen
) - 1));
682 if (opfields
[loop
].flags
& OP_SHIFT2
)
685 if (opfields
[loop
].flags
& OP_GPR
)
688 if (opfields
[loop
].flags
& OP_BITS5
)
691 if (opfields
[loop
].flags
& OP_SIGNX
)
692 printf(",%d)",(opfields
[loop
].flen
+ ((opfields
[loop
].flags
& OP_SHIFT2
) ? 2 : 0)));
700 /*---------------------------------------------------------------------------*/
708 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
712 e_endshift direction
;
715 if (proc64
&& (datalen
== 4)) {
716 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
717 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
724 /*---------------------------------------------------------------------------*/
725 /* doisa = number of MIPS ISA simulator table is being constructed for.
726 * proc64 = TRUE if constructing 64bit processor world.
727 * dofp = boolean, TRUE if FP instructions are to be included.
728 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
732 process_instructions(doarch
,features
)
734 unsigned int features
;
736 int doisa
= (doarch
& MASK_ISA
);
737 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
738 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
739 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
740 int dofp
= (features
& FEATURE_HASFPU
);
741 int fpsingle
= (features
& FEATURE_FPSINGLE
);
746 fprintf(stderr
,"process_instructions: invalid structure length\n");
750 if (proc64
&& (gprlen
!= 64)) {
751 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
755 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
758 for (loop
= 0; (loop
< limit
); loop
++)
759 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
760 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
765 printf("#if defined(SIM_MANIFESTS)\n");
766 printf("#define MIPSISA (%d)\n",doisa
);
768 printf("#define PROCESSOR_64BIT (1 == 1)\n");
769 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
770 /* The FP registers are the same width as the CPU registers: */
771 printf("#define GPRLEN (%d)\n",gprlen
);
772 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
773 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
774 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
776 printf("#define HASFPU (1 == 1)\n");
777 if (features
& FEATURE_FAST
)
778 printf("#define FASTSIM (1 == 1)\n");
779 if (features
& FEATURE_WARN_STALL
)
780 printf("#define WARN_STALL (1 == 1)\n");
781 if (features
& FEATURE_WARN_LOHI
)
782 printf("#define WARN_LOHI (1 == 1)\n");
783 if (features
& FEATURE_WARN_ZERO
)
784 printf("#define WARN_ZERO (1 == 1)\n");
785 if (features
& FEATURE_WARN_MEM
)
786 printf("#define WARN_MEM (1 == 1)\n");
787 if (features
& FEATURE_WARN_R31
)
788 printf("#define WARN_R31 (1 == 1)\n");
789 if (features
& FEATURE_WARN_RESULT
)
790 printf("#define WARN_RESULT (1 == 1)\n");
792 printf("#else /* simulator engine */\n");
794 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
795 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
797 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
798 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
801 printf("#if !defined(PROCESSOR_64BIT)\n");
802 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
806 printf("/* Actual instruction decoding block */\n");
810 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
811 limit
= (OP_MASK_OP
+ 1);
812 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
813 limit
+= (OP_MASK_SPEC
+ 1);
814 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
815 limit
+= (OP_MASK_RT
+ 1);
816 printf("else if (num == 0x11) {\n");
817 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
818 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
819 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
821 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
822 limit
+= (OP_MASK_SPEC
+ 1);
824 /* To keep this code quick, we just clear out the "to" bit
825 here. The proper (though slower) code would be to have another
826 conditional, checking whether this instruction is a branch or
827 not, before limiting the range to the bottom two bits of the
829 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
830 limit
+= (OP_MASK_COP1SPEC
+ 1);
831 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
832 limit
+= (OP_MASK_SPEC
+ 1);
833 printf("/* Total possible switch entries: %d */\n",limit
) ;
835 printf("switch (num)\n") ;
838 for (loop
= 0; (loop
< limit
); loop
++) {
839 /* First check that the ISA number we are constructing for is
840 valid, before checking if the instruction matches any of the
841 architecture specific flags. NOTE: We allow a selected ISA of
842 zero to be used to match all standard instructions. */
843 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
))) {
844 unsigned int onemask
;
845 unsigned int zeromask
;
846 unsigned int dontmask
;
849 unsigned int flags
= convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
850 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
852 if ((GETDATASIZE() == DOUBLEWORD
) && !proc64
) {
853 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
858 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
859 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
860 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
863 switch (MIPS_DECODE
[loop
].mark
) {
865 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
866 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
870 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
871 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
875 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
876 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
880 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
881 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
885 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
886 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
890 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
891 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
)) ;
895 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
899 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
902 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
903 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
906 /* Check if there are any other explicit bits in the instruction: */
907 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
908 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
910 printf(" SignalException(ReservedInstruction,instruction);\n") ;
915 if ((flags
== 0) && !(MIPS_DECODE
[loop
].flags
& NOARG
)) {
916 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE
[loop
].name
) ;
922 /* Get hold of the operands */
923 /* NOTE: If we wanted to make the simulator code smaller, we
924 * could pull these into a common sequence before we perform
925 * the instruction decoding. However, this would affect the
926 * performance since unnecessary field extraction would be
927 * occurring for certain instructions.
929 * Also we do not perform checking for multiple definitions of a
930 * particular operand here, since they are caught by the
931 * compilation of the produced code.
933 build_operands(flags
);
935 /* Finish constructing the jump address if required: */
936 if (flags
& fieldval('j'))
937 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
939 /* Now perform required operand checks: */
941 /* The following code has been removed, since it seems perfectly
942 reasonable to have a non-aligned offset that is added to another
943 non-aligned base to create an aligned address. Some more
944 information on exactly what the MIPS IV specification requires is
945 needed before deciding on the best strategy. Experimentation with a
946 VR4300 suggests that we do not need to raise the warning. */
948 /* For MIPS IV (and onwards), certain instruction operand values
949 will give undefined results. For the simulator we could
950 generate explicit exceptions (i.e. ReservedInstruction) to
951 make it easier to spot invalid use. However, for the moment we
952 just raise a warning. NOTE: This is a different check to the
953 later decoding, which checks for the final address being
955 if ((flags
& (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa
>= 4)) {
956 printf(" if (instruction & 0x%1X)\n",((flags
& fieldval('e')) ? 0x7 : ((flags
& fieldval('w')) ? 0x3 : 0x1)));
958 /* NOTE: If we change this to a SignalException(), we must
959 ensure that the following opcode processing is not
960 executed. i.e. the code falls straight out to the simulator
962 printf(" WARNING(\"Instruction has lo-order offset bits set in instruction\");\n");
967 /* The extended condition codes only appeared in ISA IV */
968 if ((flags
& fieldval('p')) && (doisa
< 4)) {
969 printf(" if (condition_code != 0)\n");
971 printf(" SignalException(ReservedInstruction,instruction);\n");
976 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && (GETDATASIZE() != WORD
)) {
977 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
982 /* The R4000 book differs slightly from the MIPS IV ISA
983 manual. An example is the sign-extension of a 64-bit processor
984 SUBU operation, and what is meant by an Undefined Result. This
985 is now provided purely as a warning. After examining a HW
986 implementation, this is now purely a warning... and the actual
987 operation is performed, with possibly undefined results. */
988 if (((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
989 /* The compiler should optimise out an OR with zero */
990 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
991 printf(" UndefinedResult();\n") ;
994 /* Check that the source is a 32bit value */
995 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) {
996 /* The compiler should optimise out an OR with zero */
997 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
998 printf(" UndefinedResult();\n") ;
1005 switch (MIPS_DECODE
[loop
].type
) {
1006 /* TODO: To make these easier to edit and maintain, they should
1007 actually be provided as source macros (or inline functions)
1008 OUTSIDE this main switch statement. The PPC simulator has a
1009 neater scheme for describing the instruction sequences. */
1014 char *basetype
= "unknown";
1015 switch (GETDATASIZE()) {
1020 basetype
= "long long";
1023 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZE());
1027 if ((MIPS_DECODE
[loop
].type
) == ADD
) {
1028 printf(" unsigned %s temp = (unsigned %s)(op1 + op2);\n",basetype
,basetype
);
1029 printf(" signed %s tempS = (signed %s)temp;\n",basetype
,basetype
);
1030 if (MIPS_DECODE
[loop
].flags
& OVERFLOW
) {
1031 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
1032 printf(" SignalException(IntegerOverflow);\n");
1035 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
1036 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1037 else /* only sign-extend when placing 32bit result in 64bit processor */
1038 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1040 printf(" unsigned %s temp = (unsigned %s)(op1 - op2);\n",basetype
,basetype
);
1041 printf(" signed %s tempS = (signed %s)temp;\n",basetype
,basetype
);
1042 if (MIPS_DECODE
[loop
].flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
1043 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
1044 printf(" SignalException(IntegerOverflow);\n");
1047 /* UNSIGNED 32bit operations on a 64bit processor should
1048 *STILL* be sign-extended. We have cheated in the
1049 data-structure, by not marking it with UNSIGNED, and not
1050 setting OVERFLOW. */
1051 if (!proc64
|| (MIPS_DECODE
[loop
].flags
& UNSIGNED
) || (GETDATASIZE() == DOUBLEWORD
))
1052 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1053 else /* only sign-extend when placing 32bit result in 64bit processor */
1054 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1060 if (features
& FEATURE_WARN_LOHI
) {
1061 printf(" CHECKHILO(\"Multiplication\");\n");
1064 if (GETDATASIZE() == DOUBLEWORD
) {
1065 printf(" uword64 mid;\n");
1066 printf(" uword64 temp;\n");
1067 printf(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
1068 printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
1069 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
1070 printf(" temp = (LO + SET64HI(WORD64LO(mid)));\n");
1071 printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n");
1072 printf(" HI += 1;\n");
1073 printf(" HI += WORD64HI(mid);\n");
1074 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
1075 printf(" LO = (temp + SET64HI(WORD64LO(mid)));\n");
1076 printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n");
1077 printf(" HI += 1;\n");
1078 printf(" HI += WORD64HI(mid);\n");
1080 printf(" uword64 temp = (op1 * op2);\n");
1081 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1082 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1089 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1091 if (features
& FEATURE_WARN_LOHI
) {
1092 printf(" CHECKHILO(\"Division\");\n");
1095 if (GETDATASIZE() == DOUBLEWORD
) {
1096 printf(" LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1097 printf(" HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU
? "u" : ""),'%',(boolU
? "u" : ""));
1099 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
1100 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
1108 int datalen
= GETDATASIZE();
1109 int bits
= ((datalen
== WORD
) ? 32 : 64);
1110 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
1112 /* Check that the specified SHIFT is valid: */
1113 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
1114 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",MIPS_DECODE
[loop
].name
);
1117 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1118 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",MIPS_DECODE
[loop
].name
);
1121 if (!(MIPS_DECODE
[loop
].flags
& LEFT
) && !(MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1122 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",MIPS_DECODE
[loop
].name
);
1125 if ((MIPS_DECODE
[loop
].flags
& LOGICAL
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1126 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1129 if (!(MIPS_DECODE
[loop
].flags
& LOGICAL
) && !(MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1130 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",MIPS_DECODE
[loop
].name
);
1133 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)) {
1134 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",MIPS_DECODE
[loop
].name
);
1138 /* If register specified shift, then extract the relevant shift amount: */
1139 if (flags
& fieldval('s'))
1140 printf(" op1 &= 0x%02X;\n",(bits
- 1));
1142 /* If HI32 specified, then shift range is 32..63 */
1143 if (MIPS_DECODE
[loop
].flags
& HI32
)
1144 printf(" op1 |= (1 << 6);\n");
1146 /* We do not need to perform pre-masking with 0xFFFFFFFF when
1147 dealing with 32bit shift lefts, since the sign-extension
1148 code will replace any remaining hi-bits: */
1149 if (MIPS_DECODE
[loop
].flags
& LEFT
)
1150 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
1152 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
1154 /* For ARITHMETIC shifts, we must duplicate the sign-bit */
1155 if (MIPS_DECODE
[loop
].flags
& ARITHMETIC
)
1156 printf(" GPR[destreg] |= ((op2 & ((%s)1 << %d)) ? ((((%s)1 << (op1 + 1)) - 1) << (%d - op1)) : 0);\n",ltype
,(bits
- 1),ltype
,(bits
- 1));
1158 /* Ensure WORD values are sign-extended into 64bit registers */
1159 if ((bits
== 32) && (gprlen
== 64))
1160 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
1165 if (MIPS_DECODE
[loop
].flags
& (HI
| LO
)) {
1166 char *regname
= ((MIPS_DECODE
[loop
].flags
& LO
) ? "LO" : "HI");
1167 if (flags
& fieldval('d'))
1168 printf(" GPR[destreg] = %s;\n",regname
);
1170 if (features
& FEATURE_WARN_LOHI
) {
1171 printf(" if (%sACCESS != 0)\n",regname
);
1172 printf(" WARNING(\"MT (move-to) over-writing %s register value\");\n",regname
);
1174 printf(" %s = op1;\n",regname
);
1176 if (features
& FEATURE_WARN_LOHI
)
1177 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname
);
1179 if (MIPS_DECODE
[loop
].flags
& SHIFT16
)
1180 printf(" GPR[destreg] = (op2 << 16);\n");
1182 /* perform conditional move */
1183 if (!(MIPS_DECODE
[loop
].flags
& EQ
)) {
1184 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",MIPS_DECODE
[loop
].name
);
1187 printf(" if (op2 %c= 0)\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1188 printf(" GPR[destreg] = op1;\n");
1193 printf(" SyncOperation(op1);\n");
1197 printf(" SignalException(SystemCall);\n");
1201 printf(" SignalException(BreakPoint);\n");
1206 int boolNOT
= (MIPS_DECODE
[loop
].flags
& NOT
);
1207 int boolEQ
= (MIPS_DECODE
[loop
].flags
& EQ
);
1208 int boolGT
= (MIPS_DECODE
[loop
].flags
& GT
);
1209 int boolLT
= (MIPS_DECODE
[loop
].flags
& LT
);
1210 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1212 if (boolGT
&& boolLT
) {
1213 fprintf(stderr
,"GT and LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1217 if (boolNOT
&& (boolGT
|| boolLT
)) {
1218 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE
[loop
].name
);
1222 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
1223 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
1224 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
1225 printf(" SignalException(Trap);\n");
1231 int boolU
= (MIPS_DECODE
[loop
].flags
& UNSIGNED
);
1233 if (!(MIPS_DECODE
[loop
].flags
& LT
)) {
1234 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1238 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1239 printf(" GPR[destreg] = 1;\n");
1241 printf(" GPR[destreg] = 0;\n");
1246 printf(" GPR[destreg] = (op1 & op2);\n");
1250 printf(" GPR[destreg] = (%sop1 | op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? "~" : ""));
1254 printf(" GPR[destreg] = (op1 ^ op2);\n");
1258 printf(" decode_coproc(instruction);\n");
1262 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1263 /* The virtual address is translated to a physical address using the TLB */
1264 /* The hint specifies a cache operation for that address */
1265 printf(" uword64 vaddr = (op1 + offset);\n");
1266 printf(" uword64 paddr;\n");
1267 printf(" int uncached;\n");
1268 /* NOTE: We are assuming that the AddressTranslation is a load: */
1269 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1270 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1273 case MADD16
: /* VR4100 specific multiply-add instructions */
1274 /* Some of this code is shared with the standard multiply
1275 routines, so an effort should be made to merge where
1277 if (features
& FEATURE_WARN_LOHI
) {
1278 printf(" CHECKHILO(\"Multiply-Add\");\n");
1280 if (features
& FEATURE_WARN_RESULT
) {
1281 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1282 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1283 printf(" WARNING(\"MADD16 operation with non-16bit operands\");\n");
1286 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1287 if (GETDATASIZE() == DOUBLEWORD
) {
1288 printf(" LO = LO + temp;\n");
1290 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
1291 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1292 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1297 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1299 printf(" if (CoProcPresent(3))\n");
1300 printf(" SignalException(CoProcessorUnusable);\n");
1303 printf(" SignalException(ReservedInstruction,instruction);\n");
1307 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1308 if (!(MIPS_DECODE
[loop
].flags
& REG
))
1309 printf(" int destreg = 31;\n");
1310 printf(" GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */\n");
1313 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1314 printf(" DSPC = op1;\n");
1315 printf(" DELAYSLOT();\n");
1318 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1319 if (MIPS_DECODE
[loop
].flags
& FP
) {
1321 printf(" if (condition_code != 0)\n");
1322 printf(" SignalException(ReservedInstruction,instruction);\n");
1323 printf(" else {\n");
1325 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
1326 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
1328 if ((MIPS_DECODE
[loop
].flags
& NOT
) && !(MIPS_DECODE
[loop
].flags
& EQ
)) {
1329 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1332 if ((MIPS_DECODE
[loop
].flags
& NOT
) && (MIPS_DECODE
[loop
].flags
& (GT
| LT
))) {
1333 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",MIPS_DECODE
[loop
].name
);
1337 if (MIPS_DECODE
[loop
].flags
& GT
)
1338 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1340 if (MIPS_DECODE
[loop
].flags
& LT
)
1341 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE
[loop
].flags
& EQ
) ? "=" : ""));
1343 if (MIPS_DECODE
[loop
].flags
& EQ
)
1344 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1347 if (MIPS_DECODE
[loop
].flags
& LINK
) {
1348 if (features
& FEATURE_WARN_R31
) {
1349 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
1350 printf(" WARNING(\"Branch with link using r31 as source operand\");\n");
1352 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1355 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1356 printf(" if (condition) {\n");
1357 printf(" DSPC = (PC + offset);\n");
1358 printf(" DELAYSLOT();\n");
1360 if ((MIPS_DECODE
[loop
].flags
& FP
) && (doisa
!= 1)) {
1361 printf(" else if (likely) {\n");
1362 printf(" NULLIFY();\n");
1364 } else if (MIPS_DECODE
[loop
].flags
& LIKELY
) {
1366 printf(" NULLIFY();\n");
1368 if ((MIPS_DECODE
[loop
].flags
& FP
) && (doisa
< 4))
1372 case PREFETCH
: /* The beginning is shared with normal load operations */
1376 int isload
= ((MIPS_DECODE
[loop
].type
== LOAD
) || (MIPS_DECODE
[loop
].type
== PREFETCH
));
1378 char *accesslength
= "<UNKNOWN>";
1380 switch (GETDATASIZE()) {
1383 accesslength
= "AccessLength_BYTE";
1388 accesslength
= "AccessLength_HALFWORD";
1393 accesslength
= "AccessLength_WORD";
1398 accesslength
= "AccessLength_DOUBLEWORD";
1402 if (MIPS_DECODE
[loop
].flags
& REG
)
1403 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
1405 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
1406 printf(" uword64 paddr;\n");
1407 printf(" int uncached;\n");
1409 /* The following check should only occur on normal (non-shifted) memory loads */
1410 if ((datalen
!= 1) && !(MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
))) {
1411 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
1412 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
1417 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
1419 if (MIPS_DECODE
[loop
].type
== PREFETCH
)
1420 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1423 printf(" %s memval;\n",(proc64
? "uword64" : "unsigned int"));
1425 if ((MIPS_DECODE
[loop
].flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
1426 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1430 if (MIPS_DECODE
[loop
].flags
& (LEFT
| RIGHT
)) {
1431 if ((MIPS_DECODE
[loop
].flags
& LEFT
) && (MIPS_DECODE
[loop
].flags
& RIGHT
)) {
1432 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",MIPS_DECODE
[loop
].name
);
1439 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE
[loop
].name
);
1442 /* fall through to... */
1445 char *maskstr
= ((datalen
== 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1447 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
1448 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
1449 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
1450 printf(" int byte;\n");
1451 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
1452 printf(" byte = ((vaddr & mask) ^ bigend);\n");
1453 printf(" if (%sBigEndianMem)\n",((MIPS_DECODE
[loop
].flags
& LEFT
) ? "!" : ""));
1454 printf(" paddr &= ~mask;\n");
1457 if (MIPS_DECODE
[loop
].flags
& LEFT
)
1458 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1460 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
1463 if (MIPS_DECODE
[loop
].flags
& LEFT
) {
1465 /* For WORD transfers work out if the value will
1466 be in the top or bottom of the DOUBLEWORD
1469 build_endian_shift(proc64
,datalen
,2,s_right
,32);
1471 if (proc64
&& (datalen
== 4)) {
1472 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1473 printf(" memval >>= 32;\n");
1477 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
1478 if (proc64
&& (datalen
== 4))
1479 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1480 } else { /* store */
1481 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
1483 build_endian_shift(proc64
,datalen
,2,s_left
,32);
1485 /* TODO: This is duplicated in the LOAD code
1486 above - and the RIGHT LOAD and STORE code
1487 below. It should be merged if possible. */
1488 if (proc64
&& (datalen
== 4)) {
1489 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1490 printf(" memval <<= 32;\n");
1494 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1496 } else { /* RIGHT */
1499 build_endian_shift(proc64
,datalen
,2,s_right
,32);
1501 if (proc64
&& (datalen
== 4)) {
1502 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1503 printf(" memval >>= 32;\n");
1508 printf(" uword64 srcmask;\n");
1509 /* All of this extra code is just a bodge
1510 required because some hosts don't allow
1511 ((v) << 64). The SPARC just leaves the (v)
1512 value un-touched. */
1513 printf(" if (byte == 0)\n");
1514 printf(" srcmask = 0;\n");
1516 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
1517 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen
);
1519 if (proc64
&& (datalen
== 4))
1520 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1521 } else { /* store */
1522 printf(" memval = (op2 << (byte * 8));\n");
1523 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength
);
1530 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE
[loop
].name
);
1533 } else { /* normal memory transfer */
1534 if (((datalen
== 8) || ((datalen
== 4) & (MIPS_DECODE
[loop
].flags
& UNSIGNED
))) && !proc64
) {
1535 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",MIPS_DECODE
[loop
].name
);
1537 /* TODO: The R4000 documentation states that a LWU
1538 instruction executed when in a 32bit processor mode
1539 should cause a ReservedInstruction exception. This
1540 will mean adding a run-time check into the code
1545 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1546 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1547 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1548 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1549 printf(" unsigned int byte;\n");
1551 if (datalen
!= 8) /* not for DOUBLEWORD */
1552 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1554 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
1556 /* The following will only make sense if the
1557 "LoadMemory" above returns a DOUBLEWORD entity */
1558 if (datalen
!= 8) { /* not for DOUBLEWORD */
1570 valmask
= 0xFFFFFFFF;
1574 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,MIPS_DECODE
[loop
].name
);
1577 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1578 /* NOTE: The R4000 user manual has the COP_LW
1579 occuring in the same cycle as the rest of the
1580 instruction, yet the MIPS IV shows the operation
1581 happening on the next cycle. To keep the simulator
1582 simple, this code follows the R4000
1583 manual. Experimentation with a silicon
1584 implementation will be needed to ascertain the
1585 correct operation. */
1586 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1587 printf(" COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)");
1589 printf(" GPR[destreg] = (");
1591 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1592 printf("SIGNEXTEND(");
1593 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
1594 if (MIPS_DECODE
[loop
].flags
& SIGNEXTEND
)
1595 printf(",%d)",(datalen
* 8));
1598 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1599 printf(" COP_LD(((instruction >> 26) & 0x3),destreg,memval);;\n");
1601 printf(" GPR[destreg] = memval;\n");
1603 } else { /* store operation */
1604 if ((datalen
== 1) || (datalen
== 2)) {
1606 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
1607 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
1608 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1609 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1610 printf(" unsigned int byte;\n");
1612 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1613 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1614 printf(" memval = (op2 << (8 * byte));\n");
1616 if (proc64
&& (datalen
== 4)) { /* proc64 SC and SW */
1617 printf(" unsigned int byte;\n");
1618 printf(" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (ReverseEndian << 2)));\n");
1619 printf(" byte = ((vaddr & 0x7) ^ (BigEndianCPU << 2));\n");
1620 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1621 printf(" memval = (((uword64)COP_SW(((instruction >> 26) & 0x3),%s)) << (8 * byte));\n",((MIPS_DECODE
[loop
].flags
& FP
) ? "fs" : "destreg"));
1623 printf(" memval = (op2 << (8 * byte));\n");
1624 } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
1625 if (MIPS_DECODE
[loop
].flags
& COPROC
)
1626 printf(" memval = (uword64)COP_S%c(((instruction >> 26) & 0x3),%s);\n",((datalen
== 8) ? 'D' : 'W'),((MIPS_DECODE
[loop
].flags
& FP
) ? "fs" : "destreg"));
1628 printf(" memval = op2;\n");
1631 if (MIPS_DECODE
[loop
].flags
& ATOMIC
)
1632 printf(" if (LLBIT)\n");
1635 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength
);
1639 if (MIPS_DECODE
[loop
].flags
& ATOMIC
) {
1640 if ((datalen
!= 4) && (datalen
!= 8)) {
1641 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",MIPS_DECODE
[loop
].name
);
1645 printf(" LLBIT = 1;\n");
1647 /* The documentation states that:
1649 SC *WILL* fail if coherent store into the same
1650 block occurs, or if an exception occurs between
1651 the LL and SC instructions.
1653 SC *MAY* fail if a load, store or prefetch is
1654 executed on the processor (VR4300 doesn't seem
1655 to), or if the instructions between the LL and
1656 SC are not in a 2048byte contiguous VM range.
1658 SC *MUST* have been preceded by an LL
1659 (i.e. LLBIT will be set), and it must use the
1660 same Vaddr, Paddr and cache-coherence algorithm
1661 as the LL (which means we should store this
1662 information from the load-conditional).
1664 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
1675 /* This code could be merged with the PREFIX generation above: */
1676 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
1677 printf(" uword64 paddr;\n");
1678 printf(" int uncached;\n");
1679 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1680 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
1684 if (MIPS_DECODE
[loop
].flags
& CONTROL
) {
1685 /* The following "magic" of interpreting the FP
1686 control-register number would not be needed if we were not
1687 trying to match our internal register numbers with those
1689 printf(" if (to) {\n");
1691 printf(" if (fs == 0) {\n");
1692 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
1693 printf(" } else if (fs == 31) {\n");
1694 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
1695 printf(" } /* else NOP */\n");
1696 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
1698 printf(" if (fs == 0) {\n");
1699 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
1700 printf(" } else if (fs == 31) {\n");
1701 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
1702 printf(" } /* else NOP */\n");
1703 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
1705 printf(" } else { /* control from */\n");
1707 printf(" if (fs == 0) {\n");
1708 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
1709 printf(" } else if (fs == 31) {\n");
1710 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
1711 printf(" } /* else NOP */\n");
1713 printf(" if (fs == 0) {\n");
1714 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
1715 printf(" } else if (fs == 31) {\n");
1716 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
1717 printf(" } /* else NOP */\n");
1721 printf(" if (to) {\n");
1722 if (GETDATASIZE() == WORD
) {
1724 printf(" if (SizeFGR() == 64) {\n");
1725 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
1726 printf(" } else { \n");
1727 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
1730 printf(" if (SizeFGR() == 64)\n");
1731 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
1733 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
1734 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1736 } else if (GETDATASIZE() == DOUBLEWORD
) {
1738 printf(" if (SizeFGR() == 64) {\n");
1739 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
1740 printf(" } else\n");
1741 printf(" if ((fs & 0x1) == 0)\n");
1743 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
1744 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
1746 if (features
& FEATURE_WARN_RESULT
) {
1748 printf(" UndefinedResult();\n");
1751 printf(" if (SizeFGR() == 64) {\n");
1752 printf(" FGR[fs] = GPR[ft];\n");
1753 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1754 printf(" } else\n");
1755 printf(" if ((fs & 0x1) == 0)\n");
1757 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
1758 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
1759 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
1760 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1762 if (features
& FEATURE_WARN_RESULT
) {
1764 printf(" UndefinedResult();\n");
1768 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
1771 printf(" } else {\n");
1772 if (GETDATASIZE() == WORD
) {
1773 if (doisa
< 4) /* write-back occurs in next cycle */
1774 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
1775 else /* in this cycle */
1776 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
1777 } else if (GETDATASIZE() == DOUBLEWORD
) {
1779 printf(" if (SizeFGR() == 64) {\n");
1780 printf(" PENDING_FILL(ft,FGR[fs]);\n");
1781 printf(" } else\n");
1782 printf(" if ((fs & 0x1) == 0) {\n");
1783 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
1784 printf(" } else {\n");
1785 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
1786 if (features
& FEATURE_WARN_RESULT
)
1787 printf(" UndefinedResult();\n");
1790 printf(" if (SizeFGR() == 64)\n");
1791 printf(" GPR[ft] = FGR[fs];\n");
1793 printf(" if ((fs & 0x1) == 0)\n");
1794 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
1795 printf(" else {\n");
1796 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
1797 if (features
& FEATURE_WARN_RESULT
)
1798 printf(" UndefinedResult();\n");
1802 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
1810 if (MIPS_DECODE
[loop
].flags
& CONDITIONAL
) {
1811 if (MIPS_DECODE
[loop
].flags
& INTEGER
) { /* moving GPR - testing FGR */
1812 printf(" if (GETFCC(condition_code) == boolean)\n");
1813 printf(" GPR[destreg] = op1;\n");
1815 if (MIPS_DECODE
[loop
].flags
& EQ
) /* moving FGR - testing GPR */
1816 printf(" if (op2 %c= 0)\n",((MIPS_DECODE
[loop
].flags
& NOT
) ? '!' : '='));
1818 printf(" if (GETFCC(condition_code) == boolean)\n");
1819 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1821 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
1823 } else { /* simple MOVE */
1824 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1829 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1830 printf(" SignalException(ReservedInstruction,instruction);\n");
1832 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
1836 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1837 printf(" SignalException(ReservedInstruction,instruction);\n");
1839 printf(" StoreFPR(destreg,format,AbsoluteValue(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,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1850 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1851 printf(" SignalException(ReservedInstruction,instruction);\n");
1853 printf(" StoreFPR(destreg,format,Multiply(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,Recip(ValueFPR(fs,format),format));\n");
1864 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1865 printf(" SignalException(ReservedInstruction,instruction);\n");
1867 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((MIPS_DECODE
[loop
].flags
& RECIP
) ? "Recip" : ""));
1878 switch (MIPS_DECODE
[loop
].type
) {
1880 op
= "FP_RM_TOPINF";
1883 op
= "FP_RM_TOMINF";
1886 op
= "FP_RM_TOZERO";
1889 op
= "FP_RM_NEAREST";
1892 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",MIPS_DECODE
[loop
].type
);
1896 switch (GETDATASIZE()) {
1904 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
1907 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1908 printf(" SignalException(ReservedInstruction,instruction);\n");
1910 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
1917 switch (GETDATASIZE()) {
1919 type
= "fmt_single";
1922 type
= "fmt_double";
1931 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZE());
1935 /* Not all combinations of conversion are valid at the
1936 moment: When converting to a fixed-point format, only
1937 floating-point sources are allowed. */
1938 printf(" if ((format == %s) | %s)\n",type
,((MIPS_DECODE
[loop
].flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
1939 printf(" SignalException(ReservedInstruction,instruction);\n");
1941 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
1946 if (MIPS_DECODE
[loop
].flags
& MULTIPLY
) {
1948 switch (GETDATASIZE()) {
1950 type
= "fmt_single";
1953 type
= "fmt_double";
1956 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZE());
1959 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
);
1961 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1962 printf(" SignalException(ReservedInstruction,instruction);\n");
1964 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1969 if (MIPS_DECODE
[loop
].flags
& MULTIPLY
) {
1971 switch (GETDATASIZE()) {
1973 type
= "fmt_single";
1976 type
= "fmt_double";
1979 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
1982 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
);
1984 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1985 printf(" SignalException(ReservedInstruction,instruction);\n");
1987 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1992 /* For the MIPS I,II or III there *MUST* be at least one
1993 instruction between the compare that sets a condition code
1994 and the branch that tests it. NOTE: However the hardware
1995 does not detect this condition. */
1996 /* Explicitly limit the operation to S and D formats: */
1997 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1998 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1999 printf(" else {\n");
2001 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
2002 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2006 printf(" int ignore = 0;\n");
2007 printf(" int less = 0;\n");
2008 printf(" int equal = 0;\n");
2009 printf(" int unordered = 1;\n");
2010 printf(" uword64 ofs = ValueFPR(fs,format);\n");
2011 printf(" uword64 oft = ValueFPR(ft,format);\n");
2012 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
2013 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
2014 printf(" FCSR |= FP_CAUSE(IO);\n");
2015 printf(" SignalException(FPE);\n");
2016 printf(" ignore = 1;\n");
2018 printf(" } else {\n");
2019 printf(" less = Less(ofs,oft,format);\n");
2020 printf(" equal = Equal(ofs,oft,format);\n");
2021 printf(" unordered = 0;\n");
2023 printf(" if (!ignore) {\n");
2024 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
2025 printf(" SETFCC(condition_code,condition);\n");
2032 fprintf(stderr
,"Unrecognised opcode type %d\n",MIPS_DECODE
[loop
].type
) ;
2037 printf(" break ;\n") ;
2041 printf("default : /* Unrecognised instruction */\n") ;
2042 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2043 printf(" break ;\n") ;
2045 printf("#endif /* simulator engine */\n");
2050 /*---------------------------------------------------------------------------*/
2052 /* The command-line feature controls are presented in a similar style
2053 to those offered by GCC, in the aim of providing a consistent
2054 interface to the user. */
2056 T_NONE
, /* no argument - mask and value fields control "feature" definition */
2057 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
2058 T_STRING
/* string argument - optionally prcededed by '=' */
2067 } machine_options
[] = {
2068 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
2069 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
2070 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
2071 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
2072 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
2073 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
2074 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
2078 /* The following architecture identies are those accepted by the "-mcpu" option: */
2079 struct architectures
{
2080 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
2081 unsigned int idflag
; /* or-ed into "isa" value */
2084 static const struct architectures available_architectures
[] = {
2085 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
2086 {0, 0} /* terminator */
2089 /*---------------------------------------------------------------------------*/
2097 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
2100 The output of this program is a block of 'C' code designed to be\n\
2101 included into the main simulation control loop of a device specific\n\
2104 fprintf(stderr
,"\nOptions:\n");
2105 fprintf(stderr
," -h --help\t\tProvide this help text\n");
2106 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
2107 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
2109 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
2110 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
2111 switch (machine_options
[loop
].type
) {
2113 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
2118 fprintf(stderr
,"=name");
2122 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options
[loop
].type
);
2125 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
2128 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
2129 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
2130 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
2131 fprintf(stderr
,"\n\n");
2134 The \"trace\" and \"warnings\" options do not define the output stream.\n\
2135 They only inform the code that includes the constructed engine to provide\n\
2136 the required features.\n\n\
2137 The \"-mips0\" option forces the construction of a simulator supporting\n\
2138 the highest available MIPS ISA supported.\n");
2143 /*---------------------------------------------------------------------------*/
2151 char *progname
= argv
[0];
2152 unsigned int doarch
= DEF_ISA
;
2153 unsigned int features
= 0; /* default state */
2156 features
|= FEATURE_HASFPU
;
2158 features
|= FEATURE_PROC32
;
2160 features
|= FEATURE_FPSINGLE
;
2162 if (features
& FEATURE_PROC32
)
2163 features
&= ~FEATURE_GP64
;
2165 features
|= FEATURE_GP64
;
2168 int this_option_optind
= (optind
? optind
: 1);
2169 int option_index
= 0;
2170 static struct option cmdline
[] = {
2173 {"warnings",0,0,'w'},
2177 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
2179 break ; /* out of the while loop */
2182 case 'h' : /* help */
2186 case 'f' : /* fast */
2187 features
|= FEATURE_FAST
;
2190 case 'w' : /* warnings */
2191 features
|= FEATURE_WARNINGS
;
2192 /* TODO: Future extension: Allow better control over the warnings generated:
2193 disable warnings -wnone ~FEATURE_WARNINGS
2194 all possible warnings -wall FEATURE_WARNINGS
2195 pipeline stall occuring -wstall FEATURE_WARN_STALL
2196 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
2197 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
2198 bad r31 use -wr31 FEATURE_WARN_R31
2199 undefined results -wresult FEATURE_WARN_RESULT
2203 case 'm' : /* machine options */
2207 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
2208 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
2209 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
2210 switch (machine_options
[loop
].type
) {
2213 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
2216 features
&= ~(machine_options
[loop
].mask
);
2217 features
|= machine_options
[loop
].value
;
2221 if (*loptarg
&& *loptarg
== '=')
2224 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
2228 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
2232 num
= strtoul(loptarg
,&loptarg
,10);
2234 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
2235 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
2240 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
2244 if (num
> MASK_ISA
) {
2245 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
2249 doarch
= ((doarch
& ~MASK_ISA
) | num
);
2250 if ((num
== 0) || (num
> 2)) {
2251 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
2252 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
2253 features
|= FEATURE_GP64
;
2254 features
&= ~FEATURE_PROC32
;
2256 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
2257 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
2258 features
&= ~FEATURE_GP64
;
2259 features
|= FEATURE_PROC32
;
2262 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
2268 if (*loptarg
&& *loptarg
== '=')
2271 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
2275 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
2279 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
2280 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
2283 if (*loptarg
&& (*loptarg
== 'r') || (*loptarg
== 'R'))
2286 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
2287 doarch
|= available_architectures
[archloop
].idflag
;
2292 if (available_architectures
[archloop
].name
== 0) {
2293 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
2297 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
2303 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
2309 if (machine_options
[loop
].name
== 0) {
2310 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
2317 /* An error message should already have been displayed */
2321 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
2326 if (optind
< argc
) {
2327 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
2328 while (optind
< argc
)
2329 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
2330 fprintf(stderr
,"\n");
2334 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
2335 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
2337 process_instructions(doarch
,features
) ;
2341 /*---------------------------------------------------------------------------*/
2342 /*> EOF gencode.c <*/