* gdbtk.tcl (files_command): Correctly insert list of files into
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
1 /*> gencode.c <*/
2 /* Instruction handling support for the MIPS architecture simulator.
3
4 This file is part of the MIPS sim
5
6 THIS SOFTWARE IS NOT COPYRIGHTED
7
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.
11
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.
15
16 $Revision$
17 $Author$
18 $Date$
19 */
20
21 #if 0
22 #define DEBUG (1) /* Just for testing */
23 #endif
24
25 /* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
26 build. It is not currently used by the MIPS simulator world
27 though. */
28
29 /* All output sent to stdout is for the simulator engine. All program
30 related warnings and errors should be sent to stderr. */
31
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
38 simulator. */
39
40 /* Notes:
41
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.
52
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).
72
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). */
77
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. */
83
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. */
97
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
102 simulator. */
103
104 /*---------------------------------------------------------------------------*/
105
106 /* Program defaults */
107 #define DEF_ISA (3)
108 #define DEF_PROC64 (1 == 1)
109 #define DEF_FP (1 == 1)
110 #define DEF_FPSINGLE (1 == 0)
111
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 */
123
124 #if 1
125 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
126 #else
127 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
128 #endif
129
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). */
140
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. */
145
146 /* FEATURE_WARN_ZERO */
147 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
148
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). */
156
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
161 events. */
162
163 /*---------------------------------------------------------------------------*/
164
165 #include <stdio.h>
166 #include <getopt.h>
167 #include <limits.h>
168 #include <errno.h>
169 #include "opcode/mips.h"
170
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)
175
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)
183
184 #define OP_SH_FORMAT (21) /* FP short format field */
185 #define OP_MASK_FORMAT (0x07)
186
187 #define OP_SH_TRUE (16)
188 #define OP_MASK_TRUE (0x01)
189
190 #define OP_SH_GE (17)
191 #define OP_MASK_GE (0x01)
192
193 #define OP_SH_UNSIGNED (16)
194 #define OP_MASK_UNSIGNED (0x01)
195
196 #define OP_SH_HINT (16)
197 #define OP_MASK_HINT (0x1F)
198
199 #if 0
200 #ifndef TRUE
201 #define TRUE (1 == 1)
202 #define FALSE (1 == 0)
203 #endif
204 #endif
205
206 /*---------------------------------------------------------------------------*/
207
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: */
212
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): */
216
217 typedef struct operand_encoding {
218 char id; /* character identifier */
219 int fpos; /* first bit position */
220 int flen; /* field length in bits */
221 char * const type;
222 char * const name;
223 unsigned int flags;
224 } operand_encoding;
225
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 */
232
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) */
264 };
265
266 /* Main instruction encoding types: */
267 typedef enum {
268 NORMAL,
269 SPECIAL,
270 REGIMM,
271 COP1,
272 COP1X,
273 COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
274 UNKNOWN
275 } inst_type;
276
277 /* Main instruction families: */
278 typedef enum {
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 */
301 FPMOVE,
302 FPMOVEC,
303 FPFLOOR,
304 FPCEIL,
305 FPTRUNC,
306 FPROUND,
307 FPNEG,
308 FPABS,
309 FPDIV,
310 FPMUL,
311 FPSUB,
312 FPADD,
313 FPPREFX,
314 FPRECIP,
315 FPSQRT,
316 FPCONVERT,
317 FPCOMPARE,
318 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
319 } opcode_type;
320
321 /* Flags field: */
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 */
331
332 /* Shorthand to get the size field from the flags value: */
333 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
334
335 /* The rest are single bit flags: */
336 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
337 #define EQ (1 << 4)
338 #define GT (1 << 5)
339 #define LT (1 << 6)
340 #define NOT (1 << 7)
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. */
368
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 */
376 } instruction;
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. */
380
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. */
384
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 */
394
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. */
399
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)},
572 };
573
574 /*---------------------------------------------------------------------------*/
575
576 /* We use the letter ordinal as the bit-position in our flags field: */
577 #define fieldval(l) (1 << ((l) - 'a'))
578
579 unsigned int
580 convert_bitmap(bitmap,onemask,zeromask,dontmask)
581 char *bitmap;
582 unsigned int *onemask, *zeromask, *dontmask;
583 {
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 */
588
589 *onemask = 0x00000000;
590 *zeromask = 0x00000000;
591 *dontmask = 0x00000000;
592
593 if (strlen(bitmap) != 32) {
594 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
595 exit(3);
596 }
597
598 for (loop = 0; (loop < 32); loop++) {
599 int oefield ;
600 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
601 if (bitmap[31 - loop] == opfields[oefield].id)
602 break;
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);
607 exit(4);
608 }
609
610 switch (bitmap[31 - loop]) {
611 case '0' : /* fixed value */
612 *zeromask |= (1 << loop);
613 lastsp = loop;
614 lastoe = -1;
615 break;
616
617 case '1' : /* fixed value */
618 *onemask |= (1 << loop);
619 lastsp = loop;
620 lastoe = -1;
621 break;
622
623 case '?' : /* fixed value */
624 *dontmask |= (1 << loop);
625 lastsp = loop;
626 lastoe = -1;
627 break;
628
629 default : /* check character encoding */
630 {
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);
636 exit(4);
637 }
638 flags |= fieldval(bitmap[31 - loop]);
639 lastsp = loop;
640 lastoe = oefield;
641 }
642 }
643 *dontmask |= (1 << loop);
644 }
645 break;
646 }
647 } else {
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);
649 exit(4);
650 }
651 }
652
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. */
656
657 return(flags);
658 }
659
660 /*---------------------------------------------------------------------------*/
661
662 static void
663 build_operands(flags)
664 unsigned int flags;
665 {
666 int loop;
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);
670
671 if (opfields[loop].flags & OP_SIGNX)
672 printf("SIGNEXTEND((%s)",opfields[loop].type);
673
674 if (opfields[loop].flags & OP_GPR)
675 printf("GPR[");
676
677 if (opfields[loop].flags & OP_SHIFT2)
678 printf("(");
679
680 printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
681
682 if (opfields[loop].flags & OP_SHIFT2)
683 printf(" << 2)");
684
685 if (opfields[loop].flags & OP_GPR)
686 printf("]");
687
688 if (opfields[loop].flags & OP_BITS5)
689 printf("&0x1F");
690
691 if (opfields[loop].flags & OP_SIGNX)
692 printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
693
694 printf(";\n");
695 }
696
697 return;
698 }
699
700 /*---------------------------------------------------------------------------*/
701
702 typedef enum {
703 s_left,
704 s_right
705 } e_endshift;
706
707 static void
708 build_endian_shift(proc64,datalen,endbit,direction,shift)
709 int proc64;
710 int datalen;
711 int endbit;
712 e_endshift direction;
713 int shift;
714 {
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);
718 printf(" }\n");
719 }
720
721 return;
722 }
723
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.
729 */
730
731 void
732 process_instructions(doarch,features)
733 unsigned int doarch;
734 unsigned int features;
735 {
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);
742 int maxisa;
743 int loop;
744
745 if (limit < 1) {
746 fprintf(stderr,"process_instructions: invalid structure length\n");
747 exit(1);
748 }
749
750 if (proc64 && (gprlen != 64)) {
751 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
752 exit(3);
753 }
754
755 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
756
757 maxisa = 0;
758 for (loop = 0; (loop < limit); loop++)
759 if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa)
760 maxisa = (MIPS_DECODE[loop].isa & MASK_ISA);
761
762 if (doisa == 0)
763 doisa = maxisa;
764
765 printf("#if defined(SIM_MANIFESTS)\n");
766 printf("#define MIPSISA (%d)\n",doisa);
767 if (proc64)
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"));
775 if (dofp)
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");
791
792 printf("#else /* simulator engine */\n");
793
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);
796 if (dofp)
797 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
798 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
799
800 if (proc64) {
801 printf("#if !defined(PROCESSOR_64BIT)\n");
802 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
803 printf("#endif\n");
804 }
805
806 printf("/* Actual instruction decoding block */\n");
807 printf("{\n");
808 {
809 int limit;
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)));
820 printf(" else\n");
821 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
822 limit += (OP_MASK_SPEC + 1);
823 printf(" else\n");
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
828 move operation. */
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) ;
834 }
835 printf("switch (num)\n") ;
836 printf("{\n");
837
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;
847 unsigned int mask;
848 unsigned int number;
849 unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
850 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
851
852 if ((GETDATASIZE() == DOUBLEWORD) && !proc64) {
853 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
854 exit(4);
855 }
856
857 #if defined(DEBUG)
858 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
859 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
860 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
861 #endif
862
863 switch (MIPS_DECODE[loop].mark) {
864 case NORMAL :
865 mask = (OP_MASK_OP << OP_SH_OP) ;
866 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
867 break ;
868
869 case SPECIAL :
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)) ;
872 break ;
873
874 case REGIMM :
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)) ;
877 break ;
878
879 case COP1 :
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)) ;
882 break ;
883
884 case COP1S :
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)) ;
887 break;
888
889 case COP1X :
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)) ;
892 break ;
893
894 default :
895 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
896 exit(5) ;
897 }
898
899 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
900
901 #if defined(DEBUG)
902 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
903 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
904 #endif
905
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) ;
909 printf(" {\n") ;
910 printf(" SignalException(ReservedInstruction,instruction);\n") ;
911 printf(" }\n") ;
912 printf(" else\n") ;
913 }
914
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) ;
917 exit(5) ;
918 }
919
920 printf(" {\n") ;
921
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.
928 *
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.
932 */
933 build_operands(flags);
934
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");
938
939 /* Now perform required operand checks: */
940
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. */
947 #if 0
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
954 valid. */
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)));
957 printf(" {\n");
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
961 control loop. */
962 printf(" WARNING(\"Instruction has lo-order offset bits set in instruction\");\n");
963 printf(" }\n");
964 }
965 #endif
966
967 /* The extended condition codes only appeared in ISA IV */
968 if ((flags & fieldval('p')) && (doisa < 4)) {
969 printf(" if (condition_code != 0)\n");
970 printf(" {\n");
971 printf(" SignalException(ReservedInstruction,instruction);\n");
972 printf(" }\n");
973 printf(" else\n");
974 }
975
976 if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
977 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
978 exit(1);
979 }
980
981 #if 1
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") ;
992 }
993 #else
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") ;
999 printf(" else\n") ;
1000 }
1001 #endif
1002
1003 printf(" {\n") ;
1004
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. */
1010
1011 case ADD:
1012 case SUB:
1013 {
1014 char *basetype = "unknown";
1015 switch (GETDATASIZE()) {
1016 case WORD :
1017 basetype = "int";
1018 break;
1019 case DOUBLEWORD :
1020 basetype = "long long";
1021 break;
1022 default :
1023 fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZE());
1024 exit(1);
1025 }
1026
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");
1033 printf(" else\n");
1034 }
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);
1039 } else { /* SUB */
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");
1045 printf(" else\n");
1046 }
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);
1055 }
1056 }
1057 break ;
1058
1059 case MUL:
1060 if (features & FEATURE_WARN_LOHI) {
1061 printf(" CHECKHILO(\"Multiplication\");\n");
1062 }
1063 printf(" {\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");
1079 } else {
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);
1083 }
1084 printf(" }\n");
1085 break ;
1086
1087 case DIV:
1088 {
1089 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1090
1091 if (features & FEATURE_WARN_LOHI) {
1092 printf(" CHECKHILO(\"Division\");\n");
1093 }
1094 printf(" {\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" : ""));
1098 } else {
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 " : ""));
1101 }
1102 printf(" }\n");
1103 }
1104 break ;
1105
1106 case SHIFT:
1107 {
1108 int datalen = GETDATASIZE();
1109 int bits = ((datalen == WORD) ? 32 : 64);
1110 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
1111
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);
1115 exit(9);
1116 }
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);
1119 exit(9);
1120 }
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);
1123 exit(9);
1124 }
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);
1127 exit(9);
1128 }
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);
1131 exit(9);
1132 }
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);
1135 exit(9);
1136 }
1137
1138 /* If register specified shift, then extract the relevant shift amount: */
1139 if (flags & fieldval('s'))
1140 printf(" op1 &= 0x%02X;\n",(bits - 1));
1141
1142 /* If HI32 specified, then shift range is 32..63 */
1143 if (MIPS_DECODE[loop].flags & HI32)
1144 printf(" op1 |= (1 << 6);\n");
1145
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");
1151 else
1152 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
1153
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));
1157
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);
1161 }
1162 break ;
1163
1164 case MOVE:
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);
1169 else {
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);
1173 }
1174 printf(" %s = op1;\n",regname);
1175 }
1176 if (features & FEATURE_WARN_LOHI)
1177 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
1178 } else
1179 if (MIPS_DECODE[loop].flags & SHIFT16)
1180 printf(" GPR[destreg] = (op2 << 16);\n");
1181 else {
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);
1185 exit(8);
1186 }
1187 printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1188 printf(" GPR[destreg] = op1;\n");
1189 }
1190 break ;
1191
1192 case SYNC:
1193 printf(" SyncOperation(op1);\n");
1194 break ;
1195
1196 case SYSCALL:
1197 printf(" SignalException(SystemCall);\n");
1198 break ;
1199
1200 case BREAK:
1201 printf(" SignalException(BreakPoint);\n");
1202 break ;
1203
1204 case TRAP:
1205 {
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);
1211
1212 if (boolGT && boolLT) {
1213 fprintf(stderr,"GT and LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1214 exit(8);
1215 }
1216
1217 if (boolNOT && (boolGT || boolLT)) {
1218 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1219 exit(8);
1220 }
1221
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");
1226 }
1227 break ;
1228
1229 case SET:
1230 {
1231 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1232
1233 if (!(MIPS_DECODE[loop].flags & LT)) {
1234 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE[loop].name);
1235 exit(8);
1236 }
1237
1238 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
1239 printf(" GPR[destreg] = 1;\n");
1240 printf(" else\n");
1241 printf(" GPR[destreg] = 0;\n");
1242 }
1243 break ;
1244
1245 case AND:
1246 printf(" GPR[destreg] = (op1 & op2);\n");
1247 break ;
1248
1249 case OR:
1250 printf(" GPR[destreg] = (%sop1 | op2);\n",((MIPS_DECODE[loop].flags & NOT) ? "~" : ""));
1251 break ;
1252
1253 case XOR:
1254 printf(" GPR[destreg] = (op1 ^ op2);\n");
1255 break ;
1256
1257 case DECODE:
1258 printf(" decode_coproc(instruction);\n");
1259 break ;
1260
1261 case CACHE:
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");
1271 break;
1272
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
1276 possible. */
1277 if (features & FEATURE_WARN_LOHI) {
1278 printf(" CHECKHILO(\"Multiply-Add\");\n");
1279 }
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");
1284 }
1285 printf(" {\n");
1286 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1287 if (GETDATASIZE() == DOUBLEWORD) {
1288 printf(" LO = LO + temp;\n");
1289 } else { /* WORD */
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);
1293 }
1294 printf(" }\n");
1295 break;
1296
1297 case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1298 if (doisa < 4) {
1299 printf(" if (CoProcPresent(3))\n");
1300 printf(" SignalException(CoProcessorUnusable);\n");
1301 printf(" else\n");
1302 }
1303 printf(" SignalException(ReservedInstruction,instruction);\n");
1304 break ;
1305
1306 case JUMP:
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");
1311 }
1312
1313 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1314 printf(" DSPC = op1;\n");
1315 printf(" DELAYSLOT();\n");
1316 break ;
1317
1318 case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1319 if (MIPS_DECODE[loop].flags & FP) {
1320 if (doisa < 4) {
1321 printf(" if (condition_code != 0)\n");
1322 printf(" SignalException(ReservedInstruction,instruction);\n");
1323 printf(" else {\n");
1324 }
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)"));
1327 } else {
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);
1330 exit(7);
1331 }
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);
1334 exit(7);
1335 }
1336 /* GT LT */
1337 if (MIPS_DECODE[loop].flags & GT)
1338 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1339 else
1340 if (MIPS_DECODE[loop].flags & LT)
1341 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1342 else
1343 if (MIPS_DECODE[loop].flags & EQ)
1344 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1345 }
1346
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");
1351 }
1352 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1353 }
1354
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");
1359 printf(" }\n");
1360 if ((MIPS_DECODE[loop].flags & FP) && (doisa != 1)) {
1361 printf(" else if (likely) {\n");
1362 printf(" NULLIFY();\n");
1363 printf(" }\n");
1364 } else if (MIPS_DECODE[loop].flags & LIKELY) {
1365 printf(" else\n");
1366 printf(" NULLIFY();\n");
1367 }
1368 if ((MIPS_DECODE[loop].flags & FP) && (doisa < 4))
1369 printf(" }\n");
1370 break ;
1371
1372 case PREFETCH: /* The beginning is shared with normal load operations */
1373 case LOAD:
1374 case STORE:
1375 {
1376 int isload = ((MIPS_DECODE[loop].type == LOAD) || (MIPS_DECODE[loop].type == PREFETCH));
1377 int datalen;
1378 char *accesslength = "<UNKNOWN>";
1379
1380 switch (GETDATASIZE()) {
1381 case BYTE :
1382 datalen = 1;
1383 accesslength = "AccessLength_BYTE";
1384 break ;
1385
1386 case HALFWORD :
1387 datalen = 2;
1388 accesslength = "AccessLength_HALFWORD";
1389 break ;
1390
1391 case WORD :
1392 datalen = 4;
1393 accesslength = "AccessLength_WORD";
1394 break ;
1395
1396 case DOUBLEWORD :
1397 datalen = 8;
1398 accesslength = "AccessLength_DOUBLEWORD";
1399 break ;
1400 }
1401
1402 if (MIPS_DECODE[loop].flags & REG)
1403 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
1404 else
1405 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
1406 printf(" uword64 paddr;\n");
1407 printf(" int uncached;\n");
1408
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"));
1413 printf(" else\n") ;
1414 }
1415
1416 printf(" {\n");
1417 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
1418
1419 if (MIPS_DECODE[loop].type == PREFETCH)
1420 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1421 else {
1422 printf(" {\n");
1423 printf(" %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
1424
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);
1427 exit(6);
1428 }
1429
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);
1433 exit(4);
1434 }
1435
1436 switch (datalen) {
1437 case 8:
1438 if (!proc64) {
1439 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE[loop].name);
1440 exit(4);
1441 }
1442 /* fall through to... */
1443 case 4:
1444 {
1445 char *maskstr = ((datalen == 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1446
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");
1455
1456 if (isload) {
1457 if (MIPS_DECODE[loop].flags & LEFT)
1458 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1459 else
1460 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
1461 }
1462
1463 if (MIPS_DECODE[loop].flags & LEFT) {
1464 if (isload) {
1465 /* For WORD transfers work out if the value will
1466 be in the top or bottom of the DOUBLEWORD
1467 returned: */
1468 #if 1
1469 build_endian_shift(proc64,datalen,2,s_right,32);
1470 #else
1471 if (proc64 && (datalen == 4)) {
1472 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1473 printf(" memval >>= 32;\n");
1474 printf(" }\n");
1475 }
1476 #endif
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));
1482 #if 1
1483 build_endian_shift(proc64,datalen,2,s_left,32);
1484 #else
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");
1491 printf(" }\n");
1492 }
1493 #endif
1494 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1495 }
1496 } else { /* RIGHT */
1497 if (isload) {
1498 #if 1
1499 build_endian_shift(proc64,datalen,2,s_right,32);
1500 #else
1501 if (proc64 && (datalen == 4)) {
1502 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1503 printf(" memval >>= 32;\n");
1504 printf(" }\n");
1505 }
1506 #endif
1507 printf(" {\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");
1515 printf(" else\n");
1516 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
1517 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen);
1518 printf(" }\n");
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);
1524 }
1525 }
1526 }
1527 break;
1528
1529 default:
1530 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
1531 exit(6);
1532 }
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);
1536 exit(4);
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
1541 sequence. */
1542 }
1543
1544 if (isload) {
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");
1550
1551 if (datalen != 8) /* not for DOUBLEWORD */
1552 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1553
1554 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
1555
1556 /* The following will only make sense if the
1557 "LoadMemory" above returns a DOUBLEWORD entity */
1558 if (datalen != 8) { /* not for DOUBLEWORD */
1559 int valmask;
1560 switch (datalen) {
1561 case 1:
1562 valmask = 0xFF;
1563 break;
1564
1565 case 2:
1566 valmask = 0xFFFF;
1567 break;
1568
1569 case 4:
1570 valmask = 0xFFFFFFFF;
1571 break;
1572
1573 default:
1574 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,MIPS_DECODE[loop].name);
1575 exit(4);
1576 }
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)");
1588 else
1589 printf(" GPR[destreg] = (");
1590
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));
1596 printf(");\n");
1597 } else {
1598 if (MIPS_DECODE[loop].flags & COPROC)
1599 printf(" COP_LD(((instruction >> 26) & 0x3),destreg,memval);;\n");
1600 else
1601 printf(" GPR[destreg] = memval;\n");
1602 }
1603 } else { /* store operation */
1604 if ((datalen == 1) || (datalen == 2)) {
1605 /* SH and SB */
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");
1611
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");
1615 } else
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"));
1622 else
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"));
1627 else
1628 printf(" memval = op2;\n");
1629 }
1630
1631 if (MIPS_DECODE[loop].flags & ATOMIC)
1632 printf(" if (LLBIT)\n");
1633
1634 printf(" {\n");
1635 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
1636 printf(" }\n");
1637 }
1638
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);
1642 exit(4);
1643 } else
1644 if (isload)
1645 printf(" LLBIT = 1;\n");
1646 else {
1647 /* The documentation states that:
1648
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.
1652
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.
1657
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).
1663 */
1664 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
1665 }
1666 }
1667 }
1668 printf(" }\n");
1669 }
1670 printf(" }\n");
1671 }
1672 break ;
1673
1674 case FPPREFX:
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");
1681 break ;
1682
1683 case FPMOVEC:
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
1688 used by GDB. */
1689 printf(" if (to) {\n");
1690 if (doisa < 4) {
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");
1697 } else {
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");
1704 }
1705 printf(" } else { /* control from */\n");
1706 if (doisa < 4) {
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");
1712 } else {
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");
1718 }
1719 printf(" }\n");
1720 } else {
1721 printf(" if (to) {\n");
1722 if (GETDATASIZE() == WORD) {
1723 if (doisa < 4) {
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");
1728 printf(" }\n");
1729 } else {
1730 printf(" if (SizeFGR() == 64)\n");
1731 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
1732 printf(" else\n");
1733 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
1734 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1735 }
1736 } else if (GETDATASIZE() == DOUBLEWORD) {
1737 if (doisa < 4) {
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");
1742 printf(" {\n");
1743 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
1744 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
1745 printf(" }\n");
1746 if (features & FEATURE_WARN_RESULT) {
1747 printf(" else\n");
1748 printf(" UndefinedResult();\n");
1749 }
1750 } else {
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");
1756 printf(" {\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");
1761 printf(" }\n");
1762 if (features & FEATURE_WARN_RESULT) {
1763 printf(" else\n");
1764 printf(" UndefinedResult();\n");
1765 }
1766 }
1767 } else {
1768 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
1769 exit(1);
1770 }
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) {
1778 if (doisa < 4) {
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");
1788 printf(" }\n");
1789 } else {
1790 printf(" if (SizeFGR() == 64)\n");
1791 printf(" GPR[ft] = FGR[fs];\n");
1792 printf(" else\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");
1799 printf(" }\n");
1800 }
1801 } else {
1802 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
1803 exit(1);
1804 }
1805 printf(" }\n");
1806 }
1807 break ;
1808
1809 case FPMOVE:
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");
1814 } else {
1815 if (MIPS_DECODE[loop].flags & EQ) /* moving FGR - testing GPR */
1816 printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1817 else
1818 printf(" if (GETFCC(condition_code) == boolean)\n");
1819 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1820 printf(" else\n");
1821 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
1822 }
1823 } else { /* simple MOVE */
1824 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1825 }
1826 break ;
1827
1828 case FPNEG:
1829 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1830 printf(" SignalException(ReservedInstruction,instruction);\n");
1831 printf(" else\n");
1832 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
1833 break ;
1834
1835 case FPABS:
1836 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1837 printf(" SignalException(ReservedInstruction,instruction);\n");
1838 printf(" else\n");
1839 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
1840 break ;
1841
1842 case FPDIV:
1843 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1844 printf(" SignalException(ReservedInstruction,instruction);\n");
1845 printf(" else\n");
1846 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1847 break ;
1848
1849 case FPMUL:
1850 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1851 printf(" SignalException(ReservedInstruction,instruction);\n");
1852 printf(" else\n");
1853 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1854 break ;
1855
1856 case FPRECIP:
1857 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1858 printf(" SignalException(ReservedInstruction,instruction);\n");
1859 printf(" else\n");
1860 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
1861 break ;
1862
1863 case FPSQRT:
1864 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1865 printf(" SignalException(ReservedInstruction,instruction);\n");
1866 printf(" else\n");
1867 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((MIPS_DECODE[loop].flags & RECIP) ? "Recip" : ""));
1868 break ;
1869
1870 case FPCEIL:
1871 case FPFLOOR:
1872 case FPTRUNC:
1873 case FPROUND:
1874 {
1875 char *op = "";
1876 char *type = "";
1877
1878 switch (MIPS_DECODE[loop].type) {
1879 case FPCEIL:
1880 op = "FP_RM_TOPINF";
1881 break;
1882 case FPFLOOR:
1883 op = "FP_RM_TOMINF";
1884 break;
1885 case FPTRUNC:
1886 op = "FP_RM_TOZERO";
1887 break;
1888 case FPROUND:
1889 op = "FP_RM_NEAREST";
1890 break;
1891 default:
1892 fprintf(stderr,"Error: Handled missing for FP reason code %d\n",MIPS_DECODE[loop].type);
1893 exit(1);
1894 }
1895
1896 switch (GETDATASIZE()) {
1897 case WORD :
1898 type = "fmt_word";
1899 break;
1900 case DOUBLEWORD :
1901 type = "fmt_long";
1902 break;
1903 default:
1904 fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
1905 exit(1);
1906 }
1907 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1908 printf(" SignalException(ReservedInstruction,instruction);\n");
1909 printf(" else\n");
1910 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
1911 }
1912 break ;
1913
1914 case FPCONVERT:
1915 {
1916 char *type = "";
1917 switch (GETDATASIZE()) {
1918 case SINGLE:
1919 type = "fmt_single";
1920 break;
1921 case DOUBLE:
1922 type = "fmt_double";
1923 break;
1924 case WORD:
1925 type = "fmt_word";
1926 break;
1927 case DOUBLEWORD:
1928 type = "fmt_long";
1929 break;
1930 default :
1931 fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZE());
1932 exit(1);
1933 }
1934
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");
1940 printf(" else\n");
1941 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
1942 }
1943 break ;
1944
1945 case FPSUB:
1946 if (MIPS_DECODE[loop].flags & MULTIPLY) {
1947 char *type = "";
1948 switch (GETDATASIZE()) {
1949 case SINGLE:
1950 type = "fmt_single";
1951 break;
1952 case DOUBLE:
1953 type = "fmt_double";
1954 break;
1955 default:
1956 fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZE());
1957 exit(1);
1958 }
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);
1960 } else {
1961 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1962 printf(" SignalException(ReservedInstruction,instruction);\n");
1963 printf(" else\n");
1964 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1965 }
1966 break ;
1967
1968 case FPADD:
1969 if (MIPS_DECODE[loop].flags & MULTIPLY) {
1970 char *type = "";
1971 switch (GETDATASIZE()) {
1972 case SINGLE:
1973 type = "fmt_single";
1974 break;
1975 case DOUBLE:
1976 type = "fmt_double";
1977 break;
1978 default:
1979 fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
1980 exit(1);
1981 }
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);
1983 } else {
1984 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1985 printf(" SignalException(ReservedInstruction,instruction);\n");
1986 printf(" else\n");
1987 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1988 }
1989 break ;
1990
1991 case FPCOMPARE:
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");
2000 if (doisa < 4) {
2001 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
2002 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2003 printf(" else\n");
2004 }
2005 printf(" {\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");
2017 printf(" }\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");
2022 printf(" }\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");
2026 printf(" }\n");
2027 printf(" }\n");
2028 printf(" }\n");
2029 break ;
2030
2031 default:
2032 fprintf(stderr,"Unrecognised opcode type %d\n",MIPS_DECODE[loop].type) ;
2033 exit(6) ;
2034 }
2035 printf(" }\n") ;
2036 printf(" }\n") ;
2037 printf(" break ;\n") ;
2038 }
2039 }
2040
2041 printf("default : /* Unrecognised instruction */\n") ;
2042 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2043 printf(" break ;\n") ;
2044 printf("}\n}\n") ;
2045 printf("#endif /* simulator engine */\n");
2046
2047 return ;
2048 }
2049
2050 /*---------------------------------------------------------------------------*/
2051
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. */
2055 typedef enum {
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 '=' */
2059 } mactypes;
2060
2061 struct {
2062 char *name;
2063 mactypes type;
2064 unsigned int mask;
2065 unsigned int value;
2066 char *desc;
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"},
2075 {0, T_NONE, 0,0}
2076 };
2077
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 */
2082 };
2083
2084 static const struct architectures available_architectures[] = {
2085 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
2086 {0, 0} /* terminator */
2087 };
2088
2089 /*---------------------------------------------------------------------------*/
2090
2091 static void
2092 usage(name)
2093 char *name;
2094 {
2095 int loop;
2096
2097 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
2098
2099 fprintf(stderr,"\
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\
2102 simulator.\n");
2103
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");
2108
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) {
2112 case T_NUM :
2113 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
2114 case T_NONE :
2115 break;
2116
2117 case T_STRING :
2118 fprintf(stderr,"=name");
2119 break;
2120
2121 default :
2122 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options[loop].type);
2123 exit(1);
2124 }
2125 fprintf(stderr,"%s\n",machine_options[loop].desc);
2126 }
2127
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");
2132
2133 fprintf(stderr,"\
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");
2139
2140 return;
2141 }
2142
2143 /*---------------------------------------------------------------------------*/
2144
2145 int
2146 main(argc,argv)
2147 int argc;
2148 char **argv;
2149 {
2150 int c;
2151 char *progname = argv[0];
2152 unsigned int doarch = DEF_ISA;
2153 unsigned int features = 0; /* default state */
2154
2155 if (DEF_FP)
2156 features |= FEATURE_HASFPU;
2157 if (!DEF_PROC64)
2158 features |= FEATURE_PROC32;
2159 if (DEF_FPSINGLE)
2160 features |= FEATURE_FPSINGLE;
2161
2162 if (features & FEATURE_PROC32)
2163 features &= ~FEATURE_GP64;
2164 else
2165 features |= FEATURE_GP64;
2166
2167 while (1) {
2168 int this_option_optind = (optind ? optind : 1);
2169 int option_index = 0;
2170 static struct option cmdline[] = {
2171 {"fast", 0,0,'f'},
2172 {"help", 0,0,'h'},
2173 {"warnings",0,0,'w'},
2174 {0, 0,0,0}
2175 };
2176
2177 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
2178 if (c == -1)
2179 break ; /* out of the while loop */
2180
2181 switch (c) {
2182 case 'h' : /* help */
2183 usage(progname);
2184 exit(0);
2185
2186 case 'f' : /* fast */
2187 features |= FEATURE_FAST;
2188 break;
2189
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
2200 */
2201 break;
2202
2203 case 'm' : /* machine options */
2204 {
2205 int loop;
2206
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) {
2211 case T_NONE :
2212 if (*loptarg) {
2213 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
2214 exit(1);
2215 }
2216 features &= ~(machine_options[loop].mask);
2217 features |= machine_options[loop].value;
2218 break;
2219
2220 case T_NUM :
2221 if (*loptarg && *loptarg == '=')
2222 loptarg++;
2223
2224 if (strcmp(machine_options[loop].name,"ips") == 0) {
2225 unsigned int num;
2226
2227 if (!*loptarg) {
2228 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
2229 exit(1);
2230 }
2231
2232 num = strtoul(loptarg,&loptarg,10);
2233
2234 if ((num == ULONG_MAX) && (errno = ERANGE)) {
2235 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
2236 exit(1);
2237 }
2238
2239 if (*loptarg) {
2240 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
2241 exit(1);
2242 }
2243
2244 if (num > MASK_ISA) {
2245 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
2246 exit(1);
2247 }
2248
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;
2255 } else {
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;
2260 }
2261 } else {
2262 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
2263 exit(1);
2264 }
2265 break;
2266
2267 case T_STRING :
2268 if (*loptarg && *loptarg == '=')
2269 loptarg++;
2270
2271 if (strcmp(machine_options[loop].name,"cpu") == 0) {
2272 int archloop;
2273
2274 if (!*loptarg) {
2275 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
2276 exit(1);
2277 }
2278
2279 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
2280 if ((*loptarg == 'v') || (*loptarg == 'V'))
2281 *loptarg++;
2282
2283 if (*loptarg && (*loptarg == 'r') || (*loptarg == 'R'))
2284 *loptarg++;
2285
2286 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
2287 doarch |= available_architectures[archloop].idflag;
2288 break;
2289 }
2290 }
2291
2292 if (available_architectures[archloop].name == 0) {
2293 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
2294 exit(1);
2295 }
2296 } else {
2297 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
2298 exit(1);
2299 }
2300 break;
2301
2302 default :
2303 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
2304 exit(1);
2305 }
2306 break;
2307 }
2308
2309 if (machine_options[loop].name == 0) {
2310 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
2311 exit(1);
2312 }
2313 }
2314 break;
2315
2316 case '?' :
2317 /* An error message should already have been displayed */
2318 exit(1);
2319
2320 default :
2321 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
2322 exit(1);
2323 }
2324 }
2325
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");
2331 exit(1);
2332 }
2333
2334 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
2335 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
2336
2337 process_instructions(doarch,features) ;
2338 return(0) ;
2339 }
2340
2341 /*---------------------------------------------------------------------------*/
2342 /*> EOF gencode.c <*/
This page took 0.096918 seconds and 4 git commands to generate.