Initial check-in of the MIPS simulator. Work still needs to be done on
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
1 /*> gencode.c <*/
2 /*---------------------------------------------------------------------------*/
3 /* $Revision$ */
4 /* $Author$ */
5 /* $Date$ */
6 /* Copyright (c) 1995, Cygnus Support */
7 /*---------------------------------------------------------------------------*/
8
9 #if 0
10 #define DEBUG (1) /* Just for testing */
11 #endif
12
13 /* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
14 build. It is not currently used by the MIPS simulator world
15 though. */
16
17 /* All output sent to stdout is for the simulator engine. All program
18 related warnings and errors should be sent to stderr. */
19
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
26 simulator. */
27
28 /* Notes:
29
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.
40
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).
60
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). */
65
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. */
71
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. */
85
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
90 simulator. */
91
92 /*---------------------------------------------------------------------------*/
93
94 /* Program defaults */
95 #define DEF_ISA (3)
96 #define DEF_PROC64 (1 == 1)
97 #define DEF_FP (1 == 1)
98 #define DEF_FPSINGLE (1 == 0)
99
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 */
112
113 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
114
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). */
125
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. */
130
131 /* FEATURE_WARN_ZERO */
132 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
133
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). */
141
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
146 events. */
147
148 /*---------------------------------------------------------------------------*/
149
150 #include <stdio.h>
151 #include <getopt.h>
152 #include <limits.h>
153 #include <errno.h>
154 #include "opcode/mips.h" /* From Cygnus progressive tree */
155
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)
172
173 #ifndef TRUE
174 #define TRUE (1 == 1)
175 #define FALSE (1 == 0)
176 #endif
177
178 /*---------------------------------------------------------------------------*/
179
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: */
184
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): */
188
189 typedef struct operand_encoding {
190 char id; /* character identifier */
191 int fpos; /* first bit position */
192 int flen; /* field length in bits */
193 char * const type;
194 char * const name;
195 unsigned int flags;
196 } operand_encoding;
197
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 */
205
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) */
237 };
238
239 /* Main instruction encoding types: */
240 typedef enum {
241 NORMAL,
242 SPECIAL,
243 REGIMM,
244 COP1,
245 COP1X,
246 UNKNOWN
247 } inst_type;
248
249 /* Main instruction families: */
250 typedef enum {
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 */
273 FPMOVE,
274 FPFLOOR,
275 FPCEIL,
276 FPTRUNC,
277 FPROUND,
278 FPNEG,
279 FPABS,
280 FPDIV,
281 FPMUL,
282 FPSUB,
283 FPADD,
284 FPMAB, /* Special encoding for MOVE, ADD and BRANCH instructions */
285 FPPREFX,
286 FPSTORE,
287 FPLOAD,
288 FPRECIP,
289 FPSQRT,
290 FPCONVERT,
291 FPCOMPARE,
292 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
293 } opcode_type;
294
295 /* Flags field: */
296 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
297 #define SIM_SH_SIZE (0)
298 #define SIM_MASK_SIZE (0x3)
299 #define BYTE (0)
300 #define HALFWORD (1)
301 #define WORD (2)
302 #define DOUBLEWORD (3)
303
304 /* Shorthand to get the size field from the flags value: */
305 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
306
307 /* The rest are single bit flags: */
308 #define COPROC (1 << 2)
309 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
310 #define EQ (1 << 4)
311 #define GT (1 << 5)
312 #define LT (1 << 6)
313 #define NOT (1 << 7)
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 */
336
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 */
344 } instruction;
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. */
348
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. */
352
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 */
362
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. */
367
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)},
536 };
537
538 /*---------------------------------------------------------------------------*/
539
540 /* We use the letter ordinal as the bit-position in our flags field: */
541 #define fieldval(l) (1 << ((l) - 'a'))
542
543 unsigned int
544 convert_bitmap(bitmap,onemask,zeromask,dontmask)
545 char *bitmap;
546 unsigned int *onemask, *zeromask, *dontmask;
547 {
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 */
552
553 *onemask = 0x00000000;
554 *zeromask = 0x00000000;
555 *dontmask = 0x00000000;
556
557 if (strlen(bitmap) != 32) {
558 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
559 exit(3);
560 }
561
562 for (loop = 0; (loop < 32); loop++) {
563 int oefield ;
564 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
565 if (bitmap[31 - loop] == opfields[oefield].id)
566 break;
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);
571 exit(4);
572 }
573
574 switch (bitmap[31 - loop]) {
575 case '0' : /* fixed value */
576 *zeromask |= (1 << loop);
577 lastsp = loop;
578 lastoe = -1;
579 break;
580
581 case '1' : /* fixed value */
582 *onemask |= (1 << loop);
583 lastsp = loop;
584 lastoe = -1;
585 break;
586
587 case '?' : /* fixed value */
588 *dontmask |= (1 << loop);
589 lastsp = loop;
590 lastoe = -1;
591 break;
592
593 default : /* check character encoding */
594 {
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);
600 exit(4);
601 }
602 flags |= fieldval(bitmap[31 - loop]);
603 lastsp = loop;
604 lastoe = oefield;
605 }
606 }
607 *dontmask |= (1 << loop);
608 }
609 break;
610 }
611 } else {
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);
613 exit(4);
614 }
615 }
616
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. */
620
621 return(flags);
622 }
623
624 /*---------------------------------------------------------------------------*/
625
626 static void
627 build_operands(flags)
628 unsigned int flags;
629 {
630 int loop;
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);
634
635 if (opfields[loop].flags & OP_SIGNX)
636 printf("SIGNEXTEND((%s)",opfields[loop].type);
637
638 if (opfields[loop].flags & (OP_GPR | OP_FGR))
639 printf("%s[",((opfields[loop].flags & OP_GPR) ? "GPR" : "FGR"));
640
641 if (opfields[loop].flags & OP_SHIFT2)
642 printf("(");
643
644 printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
645
646 if (opfields[loop].flags & OP_SHIFT2)
647 printf(" << 2)");
648
649 if (opfields[loop].flags & (OP_GPR | OP_FGR))
650 printf("]");
651
652 if (opfields[loop].flags & OP_BITS5)
653 printf("&0x1F");
654
655 if (opfields[loop].flags & OP_SIGNX)
656 printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
657
658 printf(";\n");
659 }
660
661 return;
662 }
663
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.
669 */
670
671 void
672 process_instructions(doarch,features)
673 unsigned int doarch;
674 unsigned int features;
675 {
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);
683 int loop;
684
685 if (limit < 1) {
686 fprintf(stderr,"process_instructions: invalid structure length\n");
687 exit(1);
688 }
689
690 if (proc64 && (gprlen != 64)) {
691 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
692 exit(3);
693 }
694
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);
698
699 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
700
701 printf("#if defined(SIM_MANIFESTS)\n");
702 if (proc64)
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"));
710 if (dofp)
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");
726
727 printf("#else /* simulator engine */\n");
728
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);
731 if (dofp)
732 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
733 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
734
735 if (proc64) {
736 printf("#if !defined(PROCESSOR_64BIT)\n");
737 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
738 printf("#endif\n");
739 }
740
741 printf("/* Actual instruction decoding block */\n");
742 printf("{\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") ;
750 printf("{\n");
751
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;
761 unsigned int mask;
762 unsigned int number;
763 unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
764 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
765
766 if ((GETDATASIZE() == DOUBLEWORD) && !proc64) {
767 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
768 exit(4);
769 }
770
771 #if defined(DEBUG)
772 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
773 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
774 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
775 #endif
776
777 switch (MIPS_DECODE[loop].mark) {
778 case NORMAL :
779 mask = (OP_MASK_OP << OP_SH_OP) ;
780 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
781 break ;
782
783 case SPECIAL :
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)) ;
786 break ;
787
788 case REGIMM :
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)) ;
791 break ;
792
793 case COP1 :
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)) ;
796 break ;
797
798 case COP1X :
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)) ;
801 break ;
802
803 default :
804 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
805 exit(5) ;
806 }
807
808 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
809
810 #if defined(DEBUG)
811 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
812 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
813 #endif
814
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) ;
818 printf(" {\n") ;
819 printf(" SignalException(ReservedInstruction,instruction);\n") ;
820 printf(" }\n") ;
821 printf(" else\n") ;
822 }
823
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) ;
826 exit(5) ;
827 }
828
829 printf(" {\n") ;
830
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.
837 *
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.
841 */
842 build_operands(flags);
843
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");
847
848 /* Now perform required operand checks: */
849
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. */
856 #if 0
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
863 valid. */
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)));
866 printf(" {\n");
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
870 control loop. */
871 printf(" WARNING(\"Instruction has lo-order offset bits set in instruction\");\n");
872 printf(" }\n");
873 }
874 #endif
875
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");
879 printf(" {\n");
880 printf(" SignalException(ReservedInstruction,instruction);\n");
881 printf(" }\n");
882 printf(" else\n");
883 }
884
885 if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
886 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
887 exit(1);
888 }
889
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") ;
895 printf(" else\n") ;
896 }
897
898 printf(" {\n") ;
899
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. */
904
905 case ADD:
906 case SUB :
907 {
908 char *basetype = "unknown";
909 switch (GETDATASIZE()) {
910 case WORD :
911 basetype = "int";
912 break;
913 case DOUBLEWORD :
914 basetype = "long long";
915 break;
916 default :
917 fprintf(stderr,"Opcode table error: size of SUB operands not known (%d)\n",GETDATASIZE());
918 exit(1);
919 }
920
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");
926 printf(" else\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);
931 } else { /* SUB */
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");
937 printf(" else\n");
938 }
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
942 setting OVERFLOW. */
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);
947 }
948 }
949 break ;
950
951 case MUL :
952 if (features & FEATURE_WARN_LOHI) {
953 printf(" CHECKHILO(\"Multiplication\");\n");
954 }
955 printf(" {\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");
971 } else {
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);
975 }
976 printf(" }\n");
977 break ;
978
979 case DIV :
980 {
981 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
982
983 if (features & FEATURE_WARN_LOHI) {
984 printf(" CHECKHILO(\"Division\");\n");
985 }
986 printf(" {\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 " : ""));
990 } else {
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 " : ""));
993 }
994 printf(" }\n");
995 }
996 break ;
997
998 case SHIFT :
999 {
1000 int datalen = GETDATASIZE();
1001 int bits = ((datalen == WORD) ? 32 : 64);
1002 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
1003
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);
1007 exit(9);
1008 }
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);
1011 exit(9);
1012 }
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);
1015 exit(9);
1016 }
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);
1019 exit(9);
1020 }
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);
1023 exit(9);
1024 }
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);
1027 exit(9);
1028 }
1029
1030 /* If register specified shift, then extract the relevant shift amount: */
1031 if (flags & fieldval('s'))
1032 printf(" op1 &= 0x%02X;\n",(bits - 1));
1033
1034 /* If HI32 specified, then shift range is 32..63 */
1035 if (MIPS_DECODE[loop].flags & HI32)
1036 printf(" op1 |= (1 << 6);\n");
1037
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) ? "<<" : ">>"));
1042
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));
1046
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);
1050 }
1051 break ;
1052
1053 case MOVE :
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);
1058 else {
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);
1062 }
1063 printf(" %s = op1;\n",regname);
1064 }
1065 if (features & FEATURE_WARN_LOHI)
1066 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
1067 } else
1068 if (MIPS_DECODE[loop].flags & SHIFT16)
1069 printf(" GPR[destreg] = (op2 << 16);\n");
1070 else {
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);
1074 exit(8);
1075 }
1076 printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1077 printf(" GPR[destreg] = op1;\n");
1078 }
1079 break ;
1080
1081 case SYNC :
1082 printf(" SyncOperation(op1);\n");
1083 break ;
1084
1085 case SYSCALL :
1086 printf(" SignalException(SystemCall);\n");
1087 break ;
1088
1089 case BREAK :
1090 printf(" SignalException(BreakPoint);\n");
1091 break ;
1092
1093 case TRAP :
1094 {
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);
1100
1101 if (boolGT && boolLT) {
1102 fprintf(stderr,"GT and LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1103 exit(8);
1104 }
1105
1106 if (boolNOT && (boolGT || boolLT)) {
1107 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1108 exit(8);
1109 }
1110
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");
1115 }
1116 break ;
1117
1118 case SET :
1119 {
1120 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1121
1122 if (!(MIPS_DECODE[loop].flags & LT)) {
1123 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE[loop].name);
1124 exit(8);
1125 }
1126
1127 printf(" if ((%slong long)op1 < (%slong long)op2)\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
1128 printf(" GPR[destreg] = 1;\n");
1129 printf(" else\n");
1130 printf(" GPR[destreg] = 0;\n");
1131 }
1132 break ;
1133
1134 case AND :
1135 printf(" GPR[destreg] = (op1 & op2);\n");
1136 break ;
1137
1138 case OR :
1139 printf(" GPR[destreg] = (%sop1 | op2);\n",((MIPS_DECODE[loop].flags & NOT) ? "~" : ""));
1140 break ;
1141
1142 case XOR :
1143 printf(" GPR[destreg] = (op1 ^ op2);\n");
1144 break ;
1145
1146 case DECODE :
1147 printf(" decode_coproc(instruction);\n");
1148 break ;
1149
1150 case CACHE :
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");
1160 break;
1161
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
1165 possible. */
1166 if (features & FEATURE_WARN_LOHI) {
1167 printf(" CHECKHILO(\"Multiply-Add\");\n");
1168 }
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");
1173 }
1174 printf(" {\n");
1175 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1176 if (GETDATASIZE() == DOUBLEWORD) {
1177 printf(" LO = LO + temp;\n");
1178 } else { /* WORD */
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);
1182 }
1183 printf(" }\n");
1184 break;
1185
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");
1190 printf(" else\n");
1191 }
1192 printf(" SignalException(ReservedInstruction,instruction);\n");
1193 break ;
1194
1195 case JUMP :
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");
1200 }
1201
1202 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1203 printf(" DSPC = op1;\n");
1204 printf(" DELAYSLOT();\n");
1205 break ;
1206
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);
1210 exit(7);
1211 }
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);
1214 exit(7);
1215 }
1216
1217 /* GT LT */
1218 if (MIPS_DECODE[loop].flags & GT)
1219 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1220 else
1221 if (MIPS_DECODE[loop].flags & LT)
1222 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1223 else
1224 if (MIPS_DECODE[loop].flags & EQ)
1225 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1226
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");
1231 }
1232 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1233 }
1234
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");
1239 printf(" }\n");
1240 if (MIPS_DECODE[loop].flags & LIKELY) {
1241 printf(" else\n");
1242 printf(" NULLIFY();\n");
1243 }
1244 break ;
1245
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
1249 optimised. */
1250 case PREFETCH : /* The beginning is shared with normal load operations */
1251 case LOAD :
1252 case STORE :
1253 {
1254 int isload = ((MIPS_DECODE[loop].type == LOAD) || (MIPS_DECODE[loop].type == PREFETCH));
1255 int datalen;
1256 char *accesslength = "<UNKNOWN>";
1257
1258 switch (GETDATASIZE()) {
1259 case BYTE :
1260 datalen = 1;
1261 accesslength = "AccessLength_BYTE";
1262 break ;
1263
1264 case HALFWORD :
1265 datalen = 2;
1266 accesslength = "AccessLength_HALFWORD";
1267 break ;
1268
1269 case WORD :
1270 datalen = 4;
1271 accesslength = "AccessLength_WORD";
1272 break ;
1273
1274 case DOUBLEWORD :
1275 datalen = 8;
1276 accesslength = "AccessLength_DOUBLEWORD";
1277 break ;
1278 }
1279
1280 printf(" uword64 vaddr = ((unsigned long long)op1 + offset);\n");
1281 printf(" uword64 paddr;\n");
1282 printf(" int uncached;\n");
1283
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"));
1288 printf(" else\n") ;
1289 }
1290
1291 printf(" {\n");
1292 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
1293
1294 if (MIPS_DECODE[loop].type == PREFETCH)
1295 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1296 else {
1297 printf(" {\n");
1298 printf(" %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
1299
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);
1303 exit(6);
1304 }
1305
1306 if (isload) {
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'));
1316 } else {
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);
1319 }
1320 } else
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);
1324 exit(4);
1325 }
1326
1327 switch (datalen) {
1328 case 8 :
1329 if (!proc64) {
1330 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE[loop].name);
1331 exit(4);
1332 }
1333 /* fall through to... */
1334 case 4 :
1335 {
1336 char *maskstr = ((datalen == 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1337
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");
1346
1347 if (isload) {
1348 if (MIPS_DECODE[loop].flags & LEFT)
1349 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1350 else
1351 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
1352 }
1353
1354 if (MIPS_DECODE[loop].flags & LEFT) {
1355 if (isload) {
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");
1362 printf(" }\n");
1363 }
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");
1375 printf(" }\n");
1376 }
1377 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1378 }
1379 } else { /* RIGHT */
1380 if (isload) {
1381 if (proc64 && (datalen == 4)) {
1382 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1383 printf(" memval >>= 32;\n");
1384 printf(" }\n");
1385 }
1386 printf(" {\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");
1393 printf(" else\n");
1394 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
1395 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen);
1396 printf(" }\n");
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);
1402 }
1403 }
1404 }
1405 break;
1406
1407 default :
1408 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
1409 exit(6);
1410 }
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);
1414 exit(4);
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. */
1419 }
1420
1421 if (isload) {
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");
1427
1428 if (datalen != 8) /* not for DOUBLEWORD */
1429 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1430
1431 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
1432
1433 /* The following will only make sense if the "LoadMemory" above returns a DOUBLEWORD entity */
1434 if (datalen != 8) { /* not for DOUBLEWORD */
1435 int valmask;
1436 switch (datalen) {
1437 case 1 :
1438 valmask = 0xFF;
1439 break;
1440
1441 case 2 :
1442 valmask = 0xFFFF;
1443 break;
1444
1445 case 4 :
1446 valmask = 0xFFFFFFFF;
1447 break;
1448
1449 default :
1450 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,MIPS_DECODE[loop].name);
1451 exit(4);
1452 }
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));
1460 printf(";\n");
1461 } else
1462 printf(" GPR[destreg] = memval;\n");
1463 } else { /* store operation */
1464 if ((datalen == 1) || (datalen == 2)) {
1465 /* SH and SB */
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");
1471
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");
1475 } else
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");
1483
1484 if (MIPS_DECODE[loop].flags & ATOMIC)
1485 printf(" if (LLBIT)\n");
1486
1487 printf(" {\n");
1488 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
1489 printf(" }\n");
1490 }
1491
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);
1495 exit(4);
1496 } else
1497 if (isload)
1498 printf(" LLBIT = 1;\n");
1499 else {
1500 /* The documentation states that:
1501
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.
1505
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.
1510
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).
1516 */
1517 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
1518 }
1519 }
1520 }
1521 printf(" }\n");
1522 }
1523 printf(" }\n");
1524 }
1525 break ;
1526
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. */
1531
1532 case FPMOVE :
1533 printf(" printf(\"TODO: FPMOVE operation %s */\\n\");\n",MIPS_DECODE[loop].name) ;
1534 /*
1535 MOV - MOV.fmt
1536 MOVN - MOVN.fmt
1537 MOV%c - integer <-> integer MOVF and MOVT
1538 MOV%c - FP <-> FP MOVF.fmt and MOVT.fmt
1539 */
1540 break ;
1541
1542 case FPMAB :
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");
1554 printf(" else\n");
1555 printf(" {\n");
1556 printf(" int dprec = (format & (1 << 0));\n");
1557 printf(" int to = (format & (1 << 2));\n");
1558 printf(" if (dprec)\n");
1559 printf(" {\n");
1560 printf(" if (to)\n");
1561 printf(" {\n");
1562 if ((doisa < 4) && (doisa != 0))
1563 {
1564 printf(" if (SizeFGR() == 64)\n");
1565 printf(" FGR[destreg] = GPR[hint];\n");
1566 printf(" else\n");
1567 printf(" if ((destreg & 0x1) == 0)\n");
1568 printf(" {\n");
1569 printf(" FGR[destreg + 1] = (GPR[hint] >> 32);\n");
1570 printf(" FGR[destreg] = (GPR[hint] & 0xFFFFFFFF);\n");
1571 printf(" }\n");
1572 printf(" else\n");
1573 printf(" UndefinedResult();\n");
1574 }
1575 else
1576 {
1577 printf("printf(\"TODO .. pending operation for next cycle\\n\");\n");
1578 }
1579 printf(" }\n");
1580 printf(" else\n");
1581 printf(" {\n");
1582 if ((doisa < 4) && (doisa != 0))
1583 {
1584 printf(" if (SizeFGR() == 64)\n");
1585 printf(" GPR[hint] = FGR[destreg];\n");
1586 printf(" else\n");
1587 printf(" if ((destreg & 0x1) == 0)\n");
1588 printf(" GPR[hint] = ((FGR[destreg + 1] << 32) | FGR[destreg]);\n");
1589 printf(" else\n");
1590 printf(" UndefinedResult();\n");
1591 }
1592 else
1593 {
1594 printf(" pending_reg = hint;\n");
1595 printf(" if (SizeFGR() == 64)\n");
1596 printf(" pending_data = FGR[destreg];\n");
1597 printf(" else\n");
1598 printf(" if ((destreg & 0x1) == 0)\n");
1599 printf(" pending_data = ((FGR[destreg + 1] << 32) | FGR[destreg]);\n");
1600 printf(" else\n");
1601 printf(" UndefinedResult();\n");
1602 }
1603 printf(" }\n");
1604 printf(" }\n");
1605 printf(" else /* single precision */\n");
1606 printf(" {\n");
1607 printf(" if (to)\n");
1608 printf(" {\n");
1609 if ((doisa < 4) && (doisa != 0))
1610 {
1611 printf(" if (SizeFGR() == 64)\n");
1612 printf(" FGR[destreg] = (0xDEADC0DE | (GPR[hint] & 0xFFFFFFFF));\n");
1613 printf(" else\n");
1614 printf(" FGR[destreg] = (GPR[hint] & 0xFFFFFFFF);\n");
1615 }
1616 else
1617 {
1618 printf(" pending_reg = (FPREG | destreg);\n");
1619 printf(" if (SizeFGR() == 64)\n");
1620 printf(" pending_data = (0xDEADC0DE | (GPR[hint] & 0xFFFFFFFF));\n");
1621 printf(" else\n");
1622 printf(" pending_data = (GPR[hint] & 0xFFFFFFFF);\n");
1623 }
1624 printf(" }\n");
1625 printf(" else\n");
1626 if ((doisa ==4) || (doisa == 0)) /* in this cycle */
1627 {
1628 printf(" GPR[hint] = SIGNEXTEND(FGR[destreg],32);\n");
1629 }
1630 else /* write-back occurs in next cycle */
1631 {
1632 printf(" pending_reg = hint;\n");
1633 printf(" pending_data = SIGNEXTEND(FGR[destreg],32);\n");
1634 }
1635 printf(" }\n");
1636 printf(" }\n");
1637 printf("}\n");
1638 break;
1639
1640 case FPFLOOR :
1641 printf(" printf(\"TODO: FPFLOOR operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1642 /* Lots of checks on paramater validity must be performed */
1643 break ;
1644
1645 case FPCEIL :
1646 printf(" printf(\"TODO: FPCEIL operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1647 break ;
1648
1649 case FPTRUNC :
1650 printf(" printf(\"TODO: FPTRUNC operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1651 break ;
1652
1653 case FPROUND :
1654 printf(" printf(\"TODO: FPROUND operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1655 break ;
1656
1657 case FPNEG :
1658 printf(" printf(\"TODO: FPNEG operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1659 break ;
1660
1661 case FPABS :
1662 printf(" printf(\"TODO: FPABS operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1663 break ;
1664
1665 case FPDIV :
1666 printf(" printf(\"TODO: FPDIV operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1667 break ;
1668
1669 case FPMUL :
1670 printf(" printf(\"TODO: FPMUL operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1671 break ;
1672
1673 case FPSUB :
1674 printf(" printf(\"TODO: FPSUB operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1675 break ;
1676
1677 case FPADD :
1678 printf(" printf(\"TODO: FPADD operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1679 break ;
1680
1681 case FPPREFX :
1682 printf(" printf(\"TODO: FPPREFX operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1683 break ;
1684
1685 case FPSTORE :
1686 printf(" printf(\"TODO: FPSTORE operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1687 break ;
1688
1689 case FPLOAD :
1690 printf(" printf(\"TODO: FPLOAD operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1691 break ;
1692
1693 case FPRECIP :
1694 printf(" printf(\"TODO: FPRECIP operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1695 break ;
1696
1697 case FPSQRT :
1698 printf(" printf(\"TODO: FPSQRT operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1699 break ;
1700
1701 case FPCONVERT :
1702 printf(" printf(\"TODO: FPCONVERT operation %s\\n\");\n",MIPS_DECODE[loop].name) ;
1703 break ;
1704
1705 case FPCOMPARE :
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. */
1712 break ;
1713
1714 default :
1715 fprintf(stderr,"Unrecognised opcode type %d\n",MIPS_DECODE[loop].type) ;
1716 exit(6) ;
1717 }
1718 printf(" }\n") ;
1719 printf(" }\n") ;
1720 printf(" break ;\n") ;
1721 }
1722 }
1723
1724 printf("default : /* Unrecognised instruction */\n") ;
1725 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1726 printf(" break ;\n") ;
1727 printf("}\n}\n") ;
1728 printf("#endif /* simulator engine */\n");
1729
1730 return ;
1731 }
1732
1733 /*---------------------------------------------------------------------------*/
1734
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. */
1738 typedef enum {
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 '=' */
1742 } mactypes;
1743
1744 struct {
1745 char *name;
1746 mactypes type;
1747 unsigned int mask;
1748 unsigned int value;
1749 char *desc;
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"},
1760 {0, T_NONE, 0,0}
1761 };
1762
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 */
1767 };
1768
1769 static const struct architectures available_architectures[] = {
1770 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
1771 {0, 0} /* terminator */
1772 };
1773
1774 /*---------------------------------------------------------------------------*/
1775
1776 static void
1777 usage(name)
1778 char *name;
1779 {
1780 int loop;
1781
1782 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
1783
1784 fprintf(stderr,"\
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\
1787 simulator.\n");
1788
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");
1793
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) {
1797 case T_NUM :
1798 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
1799 case T_NONE :
1800 break;
1801
1802 case T_STRING :
1803 fprintf(stderr,"=name");
1804 break;
1805
1806 default :
1807 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options[loop].type);
1808 exit(1);
1809 }
1810 fprintf(stderr,"%s\n",machine_options[loop].desc);
1811 }
1812
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");
1817
1818 fprintf(stderr,"\
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");
1824
1825 return;
1826 }
1827
1828 /*---------------------------------------------------------------------------*/
1829
1830 int
1831 main(argc,argv)
1832 int argc;
1833 char **argv;
1834 {
1835 int c;
1836 char *progname = argv[0];
1837 unsigned int doarch = DEF_ISA;
1838 unsigned int features = 0; /* default state */
1839
1840 if (DEF_FP)
1841 features |= FEATURE_HASFPU;
1842 if (!DEF_PROC64)
1843 features |= FEATURE_PROC32;
1844 if (DEF_FPSINGLE)
1845 features |= FEATURE_FPSINGLE;
1846
1847 if (features & FEATURE_PROC32)
1848 features &= ~(FEATURE_FP64 | FEATURE_GP64);
1849 else
1850 features |= (FEATURE_FP64 | FEATURE_GP64);
1851
1852 while (1) {
1853 int this_option_optind = (optind ? optind : 1);
1854 int option_index = 0;
1855 static struct option cmdline[] = {
1856 {"fast", 0,0,'f'},
1857 {"help", 0,0,'h'},
1858 {"warnings",0,0,'w'},
1859 {0, 0,0,0}
1860 };
1861
1862 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
1863 if (c == -1)
1864 break ; /* out of the while loop */
1865
1866 switch (c) {
1867 case 'h' : /* help */
1868 usage(progname);
1869 exit(0);
1870
1871 case 'f' : /* fast */
1872 features |= FEATURE_FAST;
1873 break;
1874
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
1885 */
1886 break;
1887
1888 case 'm' : /* machine options */
1889 {
1890 int loop;
1891
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) {
1896 case T_NONE :
1897 if (*loptarg) {
1898 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
1899 exit(1);
1900 }
1901 features &= ~(machine_options[loop].mask);
1902 features |= machine_options[loop].value;
1903 break;
1904
1905 case T_NUM :
1906 if (*loptarg && *loptarg == '=')
1907 loptarg++;
1908
1909 if (strcmp(machine_options[loop].name,"ips") == 0) {
1910 unsigned int num;
1911
1912 if (!*loptarg) {
1913 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
1914 exit(1);
1915 }
1916
1917 num = strtoul(loptarg,&loptarg,10);
1918
1919 if ((num == ULONG_MAX) && (errno = ERANGE)) {
1920 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
1921 exit(1);
1922 }
1923
1924 if (*loptarg) {
1925 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
1926 exit(1);
1927 }
1928
1929 if (num > MASK_ISA) {
1930 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
1931 exit(1);
1932 }
1933
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;
1940 } else {
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;
1945 }
1946 } else {
1947 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
1948 exit(1);
1949 }
1950 break;
1951
1952 case T_STRING :
1953 if (*loptarg && *loptarg == '=')
1954 loptarg++;
1955
1956 if (strcmp(machine_options[loop].name,"cpu") == 0) {
1957 int archloop;
1958
1959 if (!*loptarg) {
1960 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
1961 exit(1);
1962 }
1963
1964 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
1965 if ((*loptarg == 'v') || (*loptarg == 'V'))
1966 *loptarg++;
1967
1968 if (*loptarg && (*loptarg == 'r') || (*loptarg == 'R'))
1969 *loptarg++;
1970
1971 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
1972 doarch |= available_architectures[archloop].idflag;
1973 break;
1974 }
1975 }
1976
1977 if (available_architectures[archloop].name == 0) {
1978 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
1979 exit(1);
1980 }
1981 } else {
1982 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
1983 exit(1);
1984 }
1985 break;
1986
1987 default :
1988 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
1989 exit(1);
1990 }
1991 break;
1992 }
1993
1994 if (machine_options[loop].name == 0) {
1995 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
1996 exit(1);
1997 }
1998 }
1999 break;
2000
2001 case '?' :
2002 /* An error message should already have been displayed */
2003 exit(1);
2004
2005 default :
2006 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
2007 exit(1);
2008 }
2009 }
2010
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");
2016 exit(1);
2017 }
2018
2019 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
2020 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
2021
2022 process_instructions(doarch,features) ;
2023 return(0) ;
2024 }
2025
2026 /*---------------------------------------------------------------------------*/
2027 /*> EOF gencode.c <*/
This page took 0.090842 seconds and 5 git commands to generate.