* gencode.c: Tidied instruction decoding, and added FP instruction
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
1 /*> gencode.c <*/
2 /*---------------------------------------------------------------------------*/
3 /* $Revision$ */
4 /* $Author$ */
5 /* $Date$ */
6 /* Copyright (c) 1995, Cygnus Support */
7 /*---------------------------------------------------------------------------*/
8
9 #if 0
10 #define DEBUG (1) /* Just for testing */
11 #endif
12
13 /* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
14 build. It is not currently used by the MIPS simulator world
15 though. */
16
17 /* All output sent to stdout is for the simulator engine. All program
18 related warnings and errors should be sent to stderr. */
19
20 /* The simulator decode table is constructed this way to allow the
21 minimal code required for a particular instruction type to be
22 coded. This avoids a large simulator source file, with lots of
23 build-time conditionals controlling what code is included. However
24 this two-stage process does mean that care must be taken to ensure
25 that the correct decoding source is generated for a particular MIPS
26 simulator. */
27
28 /* Notes:
29
30 We could provide pipeline modelling by splitting the simulation of
31 instructions into seperate bytecodes for each pipeline
32 stage. e.g. for the VR4300 each instruction would generate 5
33 bytecodes, one for each pipeline stage. The simulator control would
34 then insert these into the relevant pipeline slots, and execute a
35 complete slots worth of bytecodes. However, the shape of the
36 pipeline, and what parts of each instruction are executed in each
37 pipeline stage, are different between MIPS implementations. If we
38 were to construct a simulator for a particular MIPS architecture
39 this would be a good solution.
40
41 To avoid having to provide multiple different pipeline models, a
42 simple approach for dealing with the delay slots, and register
43 dependencies has been used. The "MIPS IV Instruction Set" document
44 (Revision 3.1 - January 1995) details the standard MIPS instruction
45 set, and it defines operations in instruction (not pipe-line)
46 cycles. This means we only need to worry about a few cases where
47 the result is not available until after the next instruction, or
48 where registers in the previous two instruction cycles may be
49 corrupted. The case for corruption only occurs with HI or LO
50 register access, so we can just keep a count within the engine for
51 upto two cycles before marking the register as safe. We then only
52 need to check the safety flag when performing an update that
53 involves the HI or LO register. The only other case is the
54 BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there
55 must be an instruction between the FP CMP and the BC1[FT]. We can
56 perform the same instruction cycle count scheme, so we can raise a
57 warning if an attempt is made to access the condition code early
58 (NOTE: The hardware does not interlock on this operation, so the
59 simulator should just raise a warning).
60
61 For the situations where a result is not available until later, we
62 implent a slot to hold pending values. After the PC is incremented,
63 and before the instruction is decoded we can execute the required
64 register update (or remainder of instruction processing). */
65
66 /* The FP instruction decoding is also provided by this code. The
67 instructions are marked as "FP" ones so that we can construct a
68 simulator without an FPU if required. Similarly we mark
69 instructions as Single or Double precision, since some MIPS
70 processors only have single precision FP hardware. */
71
72 /* NOTE: Ideally all state should be passed as parameters. This allows
73 a single simulator engine to be used for multiple concurrent
74 simulations. More importantly, if a suitably powerful control is in
75 place it will allow speculative simulation, since the context can
76 be saved easily, and then restored after performing some
77 simulation. The down-side is that for certain host architectures it
78 can slow the simulator down (e.g. if globals can be accessed faster
79 than local structures). However, this is not actually the case at
80 the moment. The constructed engine uses direct names (that can be
81 macro definitions). This keeps the engine source smalled (using
82 short-hands), and it also allows the user to control whether they
83 want to use global, or indirected memory locations. i.e. whether
84 they want a single- or multi-threaded simulator engine. */
85
86 /* The constructed simulator engine contains manifests for each of the
87 features supported. The code that includes the engine can then
88 discover the available features during its build. This information
89 can be used to control run-time features provided by the final
90 simulator. */
91
92 /*---------------------------------------------------------------------------*/
93
94 /* Program defaults */
95 #define DEF_ISA (3)
96 #define DEF_PROC64 (1 == 1)
97 #define DEF_FP (1 == 1)
98 #define DEF_FPSINGLE (1 == 0)
99
100 #define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */
101 #define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */
102 #define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */
103 #define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */
104 #define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */
105 #define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */
106 #define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */
107 #define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */
108 #define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
109 #define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
110 #define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
111
112 #if 1
113 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
114 #else
115 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
116 #endif
117
118 /* FEATURE_WARN_STALL */
119 /* If MIPS I we want to raise a warning if an attempt is made to
120 access Rn in an instruction immediately following an Rn update
121 "WARNING : Invalid value read". The simulator engine is designed
122 that the previous value is read in such cases, to allow programs
123 that make use of this feature to execute. *
124 /* If MIPS II or later, attempting to read a register before the
125 update has completed will generate a "WARNING : Processor stall"
126 message (since the processor will lock the pipeline until the value
127 becomes available). */
128
129 /* FEATURE_WARN_LOHI */
130 /* Warn if an attempt is made to read the HI/LO registers before the
131 update has completed, or if an attempt is made to update the
132 registers whilst an update is occurring. */
133
134 /* FEATURE_WARN_ZERO */
135 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
136
137 /* FEATURE_WARN_R31 */
138 /* Notify the user if register r31 (the default procedure call return
139 address) is used unwisely. e.g. If r31 is used as the source in a
140 branch-and-link instruction, it would mean that an exception in the
141 delay slot instruction would not allow the branch to be re-started
142 (since r31 will have been overwritten by the link operation during
143 the first execution of the branch). */
144
145 /* FEATURE_WARN_RESULT */
146 /* Certain instructions do not raise exceptions when invalid operands
147 are given, they will just result in undefined values being
148 generated. This option controls whether the simulator flags such
149 events. */
150
151 /*---------------------------------------------------------------------------*/
152
153 #include <stdio.h>
154 #include <getopt.h>
155 #include <limits.h>
156 #include <errno.h>
157 #include "opcode/mips.h"
158
159 /* The following manifests do not appear in "include/opcode/mips.h" */
160 #define OP_SH_LOCC (8) /* FP condition code */
161 #define OP_SH_HICC (18) /* FP condition code */
162 #define OP_MASK_CC (0x07)
163
164 #define OP_SH_COP1NORM (25) /* Normal COP1 encoding */
165 #define OP_MASK_COP1NORM (0x01) /* a single bit */
166 #define OP_SH_COP1SPEC (21) /* Special COP1 encodings (within format field) */
167 #define OP_MASK_COP1SPEC (0x0F) /* Bits we are interested in */
168 #define OP_MASK_COP1SCLR (0x04) /* Bits to be explicitly cleared */
169 #define OP_MASK_COP1CMP (0x3) /* Unfortunately another conditional field needed to decode the FP instructions */
170 #define OP_SH_COP1CMP (4)
171
172 #define OP_SH_FORMAT (21) /* FP short format field */
173 #define OP_MASK_FORMAT (0x07)
174
175 #define OP_SH_TRUE (16)
176 #define OP_MASK_TRUE (0x01)
177
178 #define OP_SH_GE (17)
179 #define OP_MASK_GE (0x01)
180
181 #define OP_SH_UNSIGNED (16)
182 #define OP_MASK_UNSIGNED (0x01)
183
184 #define OP_SH_HINT (16)
185 #define OP_MASK_HINT (0x1F)
186
187 #if 0
188 #ifndef TRUE
189 #define TRUE (1 == 1)
190 #define FALSE (1 == 0)
191 #endif
192 #endif
193
194 /*---------------------------------------------------------------------------*/
195
196 /* Holding the instruction table this way makes it easier to check the
197 instruction values defined, and to add instructions to the
198 system. However, it makes the process of constructing the simulator
199 a bit more complicated: */
200
201 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
202 alphabetic characters should be used, since the letter ordinal is
203 used as a bit position): */
204
205 typedef struct operand_encoding {
206 char id; /* character identifier */
207 int fpos; /* first bit position */
208 int flen; /* field length in bits */
209 char * const type;
210 char * const name;
211 unsigned int flags;
212 } operand_encoding;
213
214 /* Values for the "flags" field: */
215 #define OP_NONE (0 << 0) /* To keep the source tidy */
216 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
217 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
218 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
219 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
220
221 struct operand_encoding opfields[] = {
222 {'0',-1,-1,"", "", (OP_NONE)}, /* special case for explicit zero */
223 {'1',-1,-1,"", "", (OP_NONE)}, /* special case for explicit one */
224 {'?',-1,-1,"", "", (OP_NONE)}, /* undefined (do not care at this level) */
225 /* The rest are the explicit operand fields: */
226 {'a', 6, 5,"int", "op1", (OP_NONE)}, /* shift amount (or hint) */
227 {'b',21, 5,"int", "fr", (OP_NONE)}, /* fr register */
228 {'c',16, 1,"int", "boolean", (OP_NONE)}, /* TRUE or FALSE boolean */
229 {'d',11, 5,"int", "destreg", (OP_NONE)}, /* integer destination/rd register */
230 {'e', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-3bits must be zero) */
231 {'f',17, 1,"int", "likely", (OP_NONE)}, /* set if branch LIKELY */
232 {'g',16, 5,"t_reg", "op2", (OP_GPR)}, /* integer source rt register */
233 {'h', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-1bit must be zero) */
234 {'i', 0,16,"t_reg", "op2", (OP_SIGNX)}, /* signed immediate (op2) */
235 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
236 {'k',16, 5,"int", "ft", (OP_NONE)},
237 {'l', 0,16,"t_reg", "offset", (OP_SIGNX | OP_SHIFT2)}, /* signed offset shifted left 2 to make 18bit signed offset */
238 {'m',21, 3,"int", "format", (OP_NONE)}, /* FP format field */
239 {'n',16, 5,"int", "hint", (OP_NONE)}, /* hint */
240 {'o',21, 5,"t_reg", "op1", (OP_GPR | OP_BITS5)}, /* integer source/rs register (but never treated as 32bit word) */
241 {'p', 8, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
242 {'q',18, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
243 {'r', 6, 5,"int", "destreg", (OP_NONE)}, /* FP fd register */
244 {'s',21, 5,"t_reg", "op1", (OP_GPR)}, /* integer source/rs register */
245 {'t',16, 5,"int", "destreg", (OP_NONE)}, /* integer target rt (destination) register */
246 {'u', 0, 4,"int", "cmpflags", (OP_NONE)}, /* FP comparison control flags */
247 {'v',11, 5,"int", "fs", (OP_NONE)}, /* FP fs register (or PREFX hint) */
248 {'w', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-2bits must be zero) */
249 {'x',23, 1,"int", "to", (OP_NONE)}, /* TRUE if move To; FALSE if move From */
250 {'y', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset */
251 {'z', 0,16,"ut_reg","op2", (OP_NONE)}, /* unsigned immediate (zero extended) */
252 };
253
254 /* Main instruction encoding types: */
255 typedef enum {
256 NORMAL,
257 SPECIAL,
258 REGIMM,
259 COP1,
260 COP1X,
261 COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
262 UNKNOWN
263 } inst_type;
264
265 /* Main instruction families: */
266 typedef enum {
267 ADD, /* res = operand1 + operand2 */
268 SUB, /* res = operand1 - operand2 */
269 MUL, /* res = operand1 * operand2 */
270 DIV, /* res = operand1 / operand2 */
271 AND, /* res = operand1 & operand2 */
272 OR, /* res = operand1 | operand2 */
273 XOR, /* res = operand1 ^ operand2 */
274 MOVE, /* res = operand1 */
275 BRANCH, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
276 JUMP, /* execute delay slot instruction before jump */
277 LOAD, /* load from memory */
278 STORE, /* store to memory */
279 PREFETCH, /* prefetch data into cache */
280 SET, /* set register on result of condition code */
281 SHIFT, /* perform a logical or arithmetic shift */
282 TRAP, /* system exception generation */
283 BREAK, /* system breakpoint exception generation */
284 SYSCALL, /* system exception generation */
285 SYNC, /* system cache control */
286 DECODE, /* co-processor instruction */
287 CACHE, /* co-processor 0 CACHE instruction */
288 MADD16, /* VR4100 specific multiply-add extensions */
289 FPMOVE,
290 FPMOVEC,
291 FPFLOOR,
292 FPCEIL,
293 FPTRUNC,
294 FPROUND,
295 FPNEG,
296 FPABS,
297 FPDIV,
298 FPMUL,
299 FPSUB,
300 FPADD,
301 FPPREFX,
302 FPRECIP,
303 FPSQRT,
304 FPCONVERT,
305 FPCOMPARE,
306 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
307 } opcode_type;
308
309 /* Flags field: */
310 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
311 #define SIM_SH_SIZE (0)
312 #define SIM_MASK_SIZE (0x7)
313 #define BYTE (0) /* 8bit */
314 #define HALFWORD (1) /* 16bit */
315 #define WORD (2) /* 32bit */
316 #define DOUBLEWORD (3) /* 64bit */
317 #define SINGLE (4) /* single precision FP */
318 #define DOUBLE (5) /* double precision FP */
319
320 /* Shorthand to get the size field from the flags value: */
321 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
322
323 /* The rest are single bit flags: */
324 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
325 #define EQ (1 << 4)
326 #define GT (1 << 5)
327 #define LT (1 << 6)
328 #define NOT (1 << 7)
329 #define LIKELY (1 << 8)
330 #define SIGNEXTEND (1 << 9)
331 #define OVERFLOW (1 << 10)
332 #define LINK (1 << 11)
333 #define ATOMIC (1 << 12)
334 #define SHIFT16 (1 << 13)
335 #define REG (1 << 14)
336 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
337 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
338 #define LOGICAL (1 << 17)
339 #define ARITHMETIC (1 << 18)
340 #define UNSIGNED (1 << 19)
341 #define HI32 (1 << 20)
342 #define HI (1 << 21) /* accesses or updates the HI register */
343 #define LO (1 << 22) /* accesses or updates the LO register */
344 #define WORD32 (1 << 23)
345 #define FP (1 << 24) /* Floating Point operation */
346 #define FIXED (1 << 25) /* fixed point arithmetic */
347 #define COPROC (1 << 26)
348 #define INTEGER (1 << 27)
349 #define CONDITIONAL (1 << 28)
350 #define RECIP (1 << 29)
351 #define CONTROL (1 << 30)
352 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
353 /* NOTE: We can overload the use of certain of these flags, since not
354 all options are applicable to all instruction types. This will free
355 up more space for new flags. */
356
357 typedef struct instruction {
358 char *name; /* ASCII mnemonic name */
359 unsigned int isa; /* MIPS ISA number where instruction introduced */
360 char *bitmap; /* 32character string describing instruction operands */
361 inst_type mark; /* type of MIPS instruction encoding */
362 opcode_type type; /* main instruction family */
363 unsigned int flags; /* flags describing instruction features */
364 } instruction;
365 /* The number of pipeline cycles taken by an instruction varies
366 between MIPS processors. This means that the information must be
367 encoded elsewhere, in a CPU specific structure. */
368
369 /* NOTE: Undefined instructions cause "Reserved Instruction"
370 exceptions. i.e. if there is no bit-mapping defined then the
371 instruction is deemed to be undefined. */
372
373 /* NOTE: The "isa" field is also used to encode flags for particular
374 chip architecture extensions. e.g. the NEC VR4100 specific
375 instructions. Normally chip extensions are added via the COP0
376 space. However, the VR4100 (and possibly other devices) also use
377 the normal instruction space. */
378 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
379 /* The other bits are allocated downwards, to avoid renumbering if we
380 have to extend the bits allocated to the pure ISA number. */
381 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
382
383 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
384 COP0 space. This means that an external decoder should be added
385 when constructing a full VR4100 simulator. However some arithmetic
386 instructions are encoded in the normal instruction space. */
387
388 struct instruction MIPS_DECODE[] = {
389 /* The instructions are alphabetical, and not in instruction bit-order: */
390 {"ABS", 1,"01000110mmm00000dddddaaaaa000101",COP1, FPABS, (FP)},
391 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */
392 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)},
393 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)},
394 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL,ADD, (WORD | WORD32)}, /* rd = rs + rt */
395 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32)},
396 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL,AND, (NONE)}, /* rd = rs AND rt */
397 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND, (NONE)},
398 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S, BRANCH, (FP)},
399 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ)},
400 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ | LIKELY)},
401 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH, (GT | EQ)},
402 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
403 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
404 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LIKELY)},
405 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT)},
406 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT | LIKELY)},
407 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ)},
408 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ | LIKELY)},
409 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH, (LT)},
410 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH, (LT | LINK)},
411 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM, BRANCH, (LT | LINK | LIKELY)},
412 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM, BRANCH, (LT | LIKELY)},
413 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ)},
414 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ | LIKELY)},
415 {"BREAK", 1,"000000????????????????????001101",SPECIAL,BREAK, (NOARG)},
416 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1, FPCEIL, (FP | FIXED | DOUBLEWORD)},
417 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1, FPCEIL, (FP | FIXED | WORD)},
418 {"COP0", 1,"010000??????????????????????????",NORMAL, DECODE, (NOARG)},
419 {"COP2", 1,"010010??????????????????????????",NORMAL, DECODE, (NOARG)},
420 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1, FPCONVERT,(FP | DOUBLE)},
421 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1, FPCONVERT,(FP | FIXED | DOUBLEWORD)},
422 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1, FPCONVERT,(FP | SINGLE)},
423 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1, FPCONVERT,(FP | FIXED | WORD)},
424 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1, FPCOMPARE,(FP)},
425 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD | CONTROL)},
426 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL,ADD, (DOUBLEWORD | OVERFLOW)},
427 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | OVERFLOW)},
428 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL,ADD, (DOUBLEWORD | UNSIGNED)},
429 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | UNSIGNED)},
430 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL,DIV, (DOUBLEWORD | HI | LO)},
431 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL,DIV, (DOUBLEWORD | UNSIGNED | HI | LO)},
432 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO)},
433 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1, FPDIV, (FP | WORD | HI | LO)},
434 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
435 {"DMADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101001",SPECIAL,MADD16, (DOUBLEWORD | HI | LO)},
436 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL,MUL, (DOUBLEWORD | HI | LO)},
437 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL,MUL, (DOUBLEWORD | UNSIGNED | HI | LO)},
438 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | DOUBLEWORD)},
439 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)},
440 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)},
441 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */
442 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
443 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
444 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */
445 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
446 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
447 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)},
448 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)},
449 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)},
450 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1, FPFLOOR, (FP | FIXED | DOUBLEWORD)},
451 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1, FPFLOOR, (FP | FIXED | WORD)},
452 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */
453 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */
454 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)},
455 {"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */
456 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
457 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */
458 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD)},
459 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
460 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
461 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | LEFT)}, /* NOTE: See "LB" comment */
462 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | RIGHT)}, /* NOTE: See "LB" comment */
463 {"LDXC1", 4,"010011sssssggggg00000rrrrr000001",COP1X, LOAD, (FP | DOUBLEWORD | COPROC | REG)},
464 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD | SIGNEXTEND)},
465 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD)},
466 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | ATOMIC | SIGNEXTEND)},
467 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | ATOMIC)},
468 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE, (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
469 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | SIGNEXTEND)},
470 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
471 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
472 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | LEFT)},
473 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | RIGHT)},
474 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD)},
475 {"LWXC1", 4,"010011sssssggggg00000rrrrr000000",COP1X, LOAD, (FP | WORD | COPROC | REG)},
476 {"MADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101000",SPECIAL,MADD16, (WORD | HI | LO)},
477 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X, FPADD, (FP | MULTIPLY | DOUBLE)},
478 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X, FPADD, (FP | MULTIPLY | SINGLE)},
479 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI)}, /* with following, from and to denoted by usage of "s" or "d" */
480 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO)},
481 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI)},
482 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO)},
483 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1, FPMOVE, (FP)},
484 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL,MOVE, (NOT | EQ)},
485 {"MOVN", 4,"01000110mmmgggggvvvvvrrrrr010011",COP1, FPMOVE, (FP | NOT | EQ)},
486 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE, (FP | CONDITIONAL | INTEGER)},
487 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1, FPMOVE, (FP | CONDITIONAL)},
488 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL,MOVE, (EQ)},
489 {"MOVZ", 4,"01000110mmmgggggvvvvvrrrrr010010",COP1, FPMOVE, (FP | EQ)},
490 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X, FPSUB, (FP | MULTIPLY | DOUBLE)},
491 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)},
492 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)},
493 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL,MUL, (WORD | WORD32 | HI | LO)},
494 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL,MUL, (WORD | WORD32 | HI | LO)},
495 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)},
496 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)},
497 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)},
498 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X, FPADD, (FP | NOT | MULTIPLY | SINGLE)},
499 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X, FPSUB, (FP | NOT | MULTIPLY | DOUBLE)},
500 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X, FPSUB, (FP | NOT | MULTIPLY | SINGLE)},
501 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL,OR, (NOT)},
502 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL,OR, (NONE)},
503 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR, (NONE)},
504 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
505 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X, FPPREFX, (FP)},
506 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1, FPRECIP, (FP)},
507 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1, FPROUND, (FP | FIXED | DOUBLEWORD)},
508 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1, FPROUND, (FP | FIXED | WORD)},
509 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1, FPSQRT, (FP | RECIP)},
510 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (BYTE)},
511 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | ATOMIC)},
512 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | ATOMIC)},
513 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD)},
514 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
515 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
516 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | LEFT)},
517 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | RIGHT)},
518 {"SDXC1", 4,"010011sssssgggggvvvvv00000001001",COP1X, STORE, (FP | DOUBLEWORD | COPROC | REG)},
519 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE, (HALFWORD)},
520 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
521 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
522 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL,SET, (LT)},
523 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT)},
524 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL,SET, (LT | UNSIGNED)},
525 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT | UNSIGNED)},
526 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1, FPSQRT, (FP)},
527 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
528 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
529 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
530 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
531 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL,SUB, (WORD | WORD32 | OVERFLOW)},
532 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1, FPSUB, (FP)},
533 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL,SUB, (WORD | WORD32)},
534 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD)},
535 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
536 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
537 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | LEFT)},
538 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | RIGHT)},
539 {"SWXC1", 4,"010011sssssgggggvvvvv00000001000",COP1X, STORE, (FP | WORD | COPROC | REG)},
540 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL,SYNC, (NONE)}, /* z = 5bit stype field */
541 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL, (NOARG)},
542 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL,TRAP, (EQ)},
543 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP, (EQ)},
544 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL,TRAP, (GT | EQ)},
545 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ)},
546 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ | UNSIGNED)},
547 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL,TRAP, (GT | EQ | UNSIGNED)},
548 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL,TRAP, (LT)},
549 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT)},
550 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT | UNSIGNED)},
551 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL,TRAP, (LT | UNSIGNED)},
552 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL,TRAP, (NOT | EQ)},
553 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM, TRAP, (NOT | EQ)},
554 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1, FPTRUNC, (FP | FIXED | DOUBLEWORD)},
555 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1, FPTRUNC, (FP | FIXED | WORD)},
556 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL,XOR, (NONE)},
557 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR, (NONE)},
558 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE, (NONE)},
559 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD, (NONE)},
560 };
561
562 /*---------------------------------------------------------------------------*/
563
564 /* We use the letter ordinal as the bit-position in our flags field: */
565 #define fieldval(l) (1 << ((l) - 'a'))
566
567 unsigned int
568 convert_bitmap(bitmap,onemask,zeromask,dontmask)
569 char *bitmap;
570 unsigned int *onemask, *zeromask, *dontmask;
571 {
572 unsigned int flags = 0x00000000;
573 int loop; /* current bitmap position */
574 int lastsp = -1; /* last bitmap field starting position */
575 int lastoe = -1; /* last bitmap field encoding */
576
577 *onemask = 0x00000000;
578 *zeromask = 0x00000000;
579 *dontmask = 0x00000000;
580
581 if (strlen(bitmap) != 32) {
582 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
583 exit(3);
584 }
585
586 for (loop = 0; (loop < 32); loop++) {
587 int oefield ;
588 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
589 if (bitmap[31 - loop] == opfields[oefield].id)
590 break;
591 if (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))) {
592 if ((lastoe != -1) && (lastoe != oefield))
593 if ((loop - lastsp) != (opfields[lastoe].flen)) {
594 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);
595 exit(4);
596 }
597
598 switch (bitmap[31 - loop]) {
599 case '0' : /* fixed value */
600 *zeromask |= (1 << loop);
601 lastsp = loop;
602 lastoe = -1;
603 break;
604
605 case '1' : /* fixed value */
606 *onemask |= (1 << loop);
607 lastsp = loop;
608 lastoe = -1;
609 break;
610
611 case '?' : /* fixed value */
612 *dontmask |= (1 << loop);
613 lastsp = loop;
614 lastoe = -1;
615 break;
616
617 default : /* check character encoding */
618 {
619 if (opfields[oefield].fpos != -1) {
620 /* If flag not set, then check starting position: */
621 if (!(flags & fieldval(bitmap[31 - loop]))) {
622 if (loop != opfields[oefield].fpos) {
623 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);
624 exit(4);
625 }
626 flags |= fieldval(bitmap[31 - loop]);
627 lastsp = loop;
628 lastoe = oefield;
629 }
630 }
631 *dontmask |= (1 << loop);
632 }
633 break;
634 }
635 } else {
636 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);
637 exit(4);
638 }
639 }
640
641 /* NOTE: Since we check for the position and size of fields when
642 parsing the "bitmap" above, we do *NOT* need to check that invalid
643 field combinations have been used. */
644
645 return(flags);
646 }
647
648 /*---------------------------------------------------------------------------*/
649
650 static void
651 build_operands(flags)
652 unsigned int flags;
653 {
654 int loop;
655 for (loop = 0; (loop < (sizeof(opfields) / sizeof(operand_encoding))); loop++)
656 if ((opfields[loop].fpos != -1) && (flags & fieldval(opfields[loop].id))) {
657 printf(" %s %s = ",opfields[loop].type,opfields[loop].name);
658
659 if (opfields[loop].flags & OP_SIGNX)
660 printf("SIGNEXTEND((%s)",opfields[loop].type);
661
662 if (opfields[loop].flags & OP_GPR)
663 printf("GPR[");
664
665 if (opfields[loop].flags & OP_SHIFT2)
666 printf("(");
667
668 printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
669
670 if (opfields[loop].flags & OP_SHIFT2)
671 printf(" << 2)");
672
673 if (opfields[loop].flags & OP_GPR)
674 printf("]");
675
676 if (opfields[loop].flags & OP_BITS5)
677 printf("&0x1F");
678
679 if (opfields[loop].flags & OP_SIGNX)
680 printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
681
682 printf(";\n");
683 }
684
685 return;
686 }
687
688 /*---------------------------------------------------------------------------*/
689 /* doisa = number of MIPS ISA simulator table is being constructed for.
690 * proc64 = TRUE if constructing 64bit processor world.
691 * dofp = boolean, TRUE if FP instructions are to be included.
692 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
693 */
694
695 void
696 process_instructions(doarch,features)
697 unsigned int doarch;
698 unsigned int features;
699 {
700 int doisa = (doarch & MASK_ISA);
701 int limit = (sizeof(MIPS_DECODE) / sizeof(instruction));
702 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
703 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
704 int dofp = (features & FEATURE_HASFPU);
705 int fpsingle = (features & FEATURE_FPSINGLE);
706 int maxisa;
707 int loop;
708
709 if (limit < 1) {
710 fprintf(stderr,"process_instructions: invalid structure length\n");
711 exit(1);
712 }
713
714 if (proc64 && (gprlen != 64)) {
715 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
716 exit(3);
717 }
718
719 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
720
721 maxisa = 0;
722 for (loop = 0; (loop < limit); loop++)
723 if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa)
724 maxisa = (MIPS_DECODE[loop].isa & MASK_ISA);
725
726 if (doisa == 0)
727 doisa = maxisa;
728
729 printf("#if defined(SIM_MANIFESTS)\n");
730 printf("#define MIPSISA (%d)\n",doisa);
731 if (proc64)
732 printf("#define PROCESSOR_64BIT (1 == 1)\n");
733 printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
734 /* The FP registers are the same width as the CPU registers: */
735 printf("#define GPRLEN (%d)\n",gprlen);
736 printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
737 printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
738 printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
739 if (dofp)
740 printf("#define HASFPU (1 == 1)\n");
741 if (features & FEATURE_FAST)
742 printf("#define FASTSIM (1 == 1)\n");
743 if (features & FEATURE_WARN_STALL)
744 printf("#define WARN_STALL (1 == 1)\n");
745 if (features & FEATURE_WARN_LOHI)
746 printf("#define WARN_LOHI (1 == 1)\n");
747 if (features & FEATURE_WARN_ZERO)
748 printf("#define WARN_ZERO (1 == 1)\n");
749 if (features & FEATURE_WARN_MEM)
750 printf("#define WARN_MEM (1 == 1)\n");
751 if (features & FEATURE_WARN_R31)
752 printf("#define WARN_R31 (1 == 1)\n");
753 if (features & FEATURE_WARN_RESULT)
754 printf("#define WARN_RESULT (1 == 1)\n");
755
756 printf("#else /* simulator engine */\n");
757
758 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
759 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
760 if (dofp)
761 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
762 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
763
764 if (proc64) {
765 printf("#if !defined(PROCESSOR_64BIT)\n");
766 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
767 printf("#endif\n");
768 }
769
770 printf("/* Actual instruction decoding block */\n");
771 printf("{\n");
772 {
773 int limit;
774 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
775 limit = (OP_MASK_OP + 1);
776 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
777 limit += (OP_MASK_SPEC + 1);
778 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
779 limit += (OP_MASK_RT + 1);
780 printf("else if (num == 0x11) {\n");
781 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
782 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
783 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
784 printf(" else\n");
785 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
786 limit += (OP_MASK_SPEC + 1);
787 printf(" else\n");
788 /* To keep this code quick, we just clear out the "to" bit
789 here. The proper (though slower) code would be to have another
790 conditional, checking whether this instruction is a branch or
791 not, before limiting the range to the bottom two bits of the
792 move operation. */
793 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
794 limit += (OP_MASK_COP1SPEC + 1);
795 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
796 limit += (OP_MASK_SPEC + 1);
797 printf("/* Total possible switch entries: %d */\n",limit) ;
798 }
799 printf("switch (num)\n") ;
800 printf("{\n");
801
802 for (loop = 1; (loop < limit); loop++) {
803 /* First check that the ISA number we are constructing for is
804 valid, before checking if the instruction matches any of the
805 architecture specific flags. NOTE: We allow a selected ISA of
806 zero to be used to match all standard instructions. */
807 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))) {
808 unsigned int onemask;
809 unsigned int zeromask;
810 unsigned int dontmask;
811 unsigned int mask;
812 unsigned int number;
813 unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
814 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
815
816 if ((GETDATASIZE() == DOUBLEWORD) && !proc64) {
817 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
818 exit(4);
819 }
820
821 #if defined(DEBUG)
822 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
823 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
824 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
825 #endif
826
827 switch (MIPS_DECODE[loop].mark) {
828 case NORMAL :
829 mask = (OP_MASK_OP << OP_SH_OP) ;
830 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
831 break ;
832
833 case SPECIAL :
834 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
835 number = ((OP_MASK_OP + 1) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
836 break ;
837
838 case REGIMM :
839 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_RT << OP_SH_RT)) ;
840 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_RT) & OP_MASK_RT)) ;
841 break ;
842
843 case COP1 :
844 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
845 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
846 break ;
847
848 case COP1S :
849 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_COP1SPEC << OP_SH_COP1SPEC)) ;
850 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_COP1SPEC) & OP_MASK_COP1SPEC)) ;
851 break;
852
853 case COP1X :
854 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
855 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)) ;
856 break ;
857
858 default :
859 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
860 exit(5) ;
861 }
862
863 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
864
865 #if defined(DEBUG)
866 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
867 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
868 #endif
869
870 /* Check if there are any other explicit bits in the instruction: */
871 if ((~mask & (onemask | zeromask)) != 0x00000000) {
872 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
873 printf(" {\n") ;
874 printf(" SignalException(ReservedInstruction,instruction);\n") ;
875 printf(" }\n") ;
876 printf(" else\n") ;
877 }
878
879 if ((flags == 0) && !(MIPS_DECODE[loop].flags & NOARG)) {
880 fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE[loop].name) ;
881 exit(5) ;
882 }
883
884 printf(" {\n") ;
885
886 /* Get hold of the operands */
887 /* NOTE: If we wanted to make the simulator code smaller, we
888 * could pull these into a common sequence before we perform
889 * the instruction decoding. However, this would affect the
890 * performance since unnecessary field extraction would be
891 * occurring for certain instructions.
892 *
893 * Also we do not perform checking for multiple definitions of a
894 * particular operand here, since they are caught by the
895 * compilation of the produced code.
896 */
897 build_operands(flags);
898
899 /* Finish constructing the jump address if required: */
900 if (flags & fieldval('j'))
901 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
902
903 /* Now perform required operand checks: */
904
905 /* The following code has been removed, since it seems perfectly
906 reasonable to have a non-aligned offset that is added to another
907 non-aligned base to create an aligned address. Some more
908 information on exactly what the MIPS IV specification requires is
909 needed before deciding on the best strategy. Experimentation with a
910 VR4300 suggests that we do not need to raise the warning. */
911 #if 0
912 /* For MIPS IV (and onwards), certain instruction operand values
913 will give undefined results. For the simulator we could
914 generate explicit exceptions (i.e. ReservedInstruction) to
915 make it easier to spot invalid use. However, for the moment we
916 just raise a warning. NOTE: This is a different check to the
917 later decoding, which checks for the final address being
918 valid. */
919 if ((flags & (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa >= 4)) {
920 printf(" if (instruction & 0x%1X)\n",((flags & fieldval('e')) ? 0x7 : ((flags & fieldval('w')) ? 0x3 : 0x1)));
921 printf(" {\n");
922 /* NOTE: If we change this to a SignalException(), we must
923 ensure that the following opcode processing is not
924 executed. i.e. the code falls straight out to the simulator
925 control loop. */
926 printf(" WARNING(\"Instruction has lo-order offset bits set in instruction\");\n");
927 printf(" }\n");
928 }
929 #endif
930
931 /* The extended condition codes only appeared in ISA IV */
932 if ((flags & fieldval('p')) && (doisa < 4)) {
933 printf(" if (condition_code != 0)\n");
934 printf(" {\n");
935 printf(" SignalException(ReservedInstruction,instruction);\n");
936 printf(" }\n");
937 printf(" else\n");
938 }
939
940 if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
941 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
942 exit(1);
943 }
944
945 #if 1
946 /* The R4000 book differs slightly from the MIPS IV ISA
947 manual. An example is the sign-extension of a 64-bit processor
948 SUBU operation, and what is meant by an Undefined Result. This
949 is now provided purely as a warning. After examining a HW
950 implementation, this is now purely a warning... and the actual
951 operation is performed, with possibly undefined results. */
952 if (((MIPS_DECODE[loop].flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
953 /* The compiler should optimise out an OR with zero */
954 printf(" if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
955 printf(" UndefinedResult();\n") ;
956 }
957 #else
958 /* Check that the source is a 32bit value */
959 if ((MIPS_DECODE[loop].flags & WORD32) && proc64) {
960 /* The compiler should optimise out an OR with zero */
961 printf(" if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
962 printf(" UndefinedResult();\n") ;
963 printf(" else\n") ;
964 }
965 #endif
966
967 printf(" {\n") ;
968
969 switch (MIPS_DECODE[loop].type) {
970 /* TODO: To make these easier to edit and maintain, they should
971 actually be provided as source macros (or inline functions)
972 OUTSIDE this main switch statement. The PPC simulator has a
973 neater scheme for describing the instruction sequences. */
974
975 case ADD:
976 case SUB:
977 {
978 char *basetype = "unknown";
979 switch (GETDATASIZE()) {
980 case WORD :
981 basetype = "int";
982 break;
983 case DOUBLEWORD :
984 basetype = "long long";
985 break;
986 default :
987 fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZE());
988 exit(1);
989 }
990
991 if ((MIPS_DECODE[loop].type) == ADD) {
992 printf(" unsigned %s temp = (unsigned %s)(op1 + op2);\n",basetype,basetype);
993 printf(" signed %s tempS = (signed %s)temp;\n",basetype,basetype);
994 if (MIPS_DECODE[loop].flags & OVERFLOW) {
995 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
996 printf(" SignalException(IntegerOverflow);\n");
997 printf(" else\n");
998 }
999 if (!proc64 || (MIPS_DECODE[loop].flags & UNSIGNED) || (GETDATASIZE() == DOUBLEWORD))
1000 printf(" GPR[destreg] = (%s)temp;\n",regtype);
1001 else /* only sign-extend when placing 32bit result in 64bit processor */
1002 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
1003 } else { /* SUB */
1004 printf(" unsigned %s temp = (unsigned %s)(op1 - op2);\n",basetype,basetype);
1005 printf(" signed %s tempS = (signed %s)temp;\n",basetype,basetype);
1006 if (MIPS_DECODE[loop].flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
1007 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
1008 printf(" SignalException(IntegerOverflow);\n");
1009 printf(" else\n");
1010 }
1011 /* UNSIGNED 32bit operations on a 64bit processor should
1012 *STILL* be sign-extended. We have cheated in the
1013 data-structure, by not marking it with UNSIGNED, and not
1014 setting OVERFLOW. */
1015 if (!proc64 || (MIPS_DECODE[loop].flags & UNSIGNED) || (GETDATASIZE() == DOUBLEWORD))
1016 printf(" GPR[destreg] = (%s)temp;\n",regtype);
1017 else /* only sign-extend when placing 32bit result in 64bit processor */
1018 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
1019 }
1020 }
1021 break ;
1022
1023 case MUL:
1024 if (features & FEATURE_WARN_LOHI) {
1025 printf(" CHECKHILO(\"Multiplication\");\n");
1026 }
1027 printf(" {\n");
1028 if (GETDATASIZE() == DOUBLEWORD) {
1029 printf(" uword64 mid;\n");
1030 printf(" uword64 temp;\n");
1031 printf(" LO = ((op1 & 0xFFFFFFFF) * (op2 & 0xFFFFFFFF));\n");
1032 printf(" HI = ((op1 >> 32) * (op2 >> 32));\n");
1033 printf(" mid = ((op1 >> 32) * (op2 & 0xFFFFFFFF));\n");
1034 printf(" temp = (LO + ((mid & 0xFFFFFFFF) << 32));\n");
1035 printf(" if ((temp == mid) ? (LO != 0) : (temp < mid))\n");
1036 printf(" HI += 1;\n");
1037 printf(" HI += ((mid >> 32) & 0xFFFFFFFF);\n");
1038 printf(" mid = ((op1 & 0xFFFFFFFF) * (op2 >> 32));\n");
1039 printf(" LO = (temp + ((mid & 0xFFFFFFFF) << 32));\n");
1040 printf(" if ((LO == mid) ? (temp != 0) : (LO < mid))\n");
1041 printf(" HI += 1;\n");
1042 printf(" HI += ((mid >> 32) & 0xFFFFFFFF);\n");
1043 } else {
1044 printf(" uword64 temp = (op1 * op2);\n");
1045 printf(" LO = SIGNEXTEND((%s)(temp & 0xFFFFFFFF),32);\n",regtype);
1046 printf(" HI = SIGNEXTEND((%s)((temp >> 32) & 0xFFFFFFFF),32);\n",regtype);
1047 }
1048 printf(" }\n");
1049 break ;
1050
1051 case DIV:
1052 {
1053 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1054
1055 if (features & FEATURE_WARN_LOHI) {
1056 printf(" CHECKHILO(\"Division\");\n");
1057 }
1058 printf(" {\n");
1059 if (GETDATASIZE() == DOUBLEWORD) {
1060 printf(" LO = ((%slong long)op1 / (%slong long)op2);\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
1061 printf(" HI = ((%slong long)op1 %c (%slong long)op2);\n",(boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
1062 } else {
1063 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
1064 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
1065 }
1066 printf(" }\n");
1067 }
1068 break ;
1069
1070 case SHIFT:
1071 {
1072 int datalen = GETDATASIZE();
1073 int bits = ((datalen == WORD) ? 32 : 64);
1074 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
1075
1076 /* Check that the specified SHIFT is valid: */
1077 if ((datalen == BYTE) || (datalen == HALFWORD)) {
1078 fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",MIPS_DECODE[loop].name);
1079 exit(9);
1080 }
1081 if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & RIGHT)) {
1082 fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",MIPS_DECODE[loop].name);
1083 exit(9);
1084 }
1085 if (!(MIPS_DECODE[loop].flags & LEFT) && !(MIPS_DECODE[loop].flags & RIGHT)) {
1086 fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",MIPS_DECODE[loop].name);
1087 exit(9);
1088 }
1089 if ((MIPS_DECODE[loop].flags & LOGICAL) && (MIPS_DECODE[loop].flags & ARITHMETIC)) {
1090 fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",MIPS_DECODE[loop].name);
1091 exit(9);
1092 }
1093 if (!(MIPS_DECODE[loop].flags & LOGICAL) && !(MIPS_DECODE[loop].flags & ARITHMETIC)) {
1094 fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",MIPS_DECODE[loop].name);
1095 exit(9);
1096 }
1097 if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & ARITHMETIC)) {
1098 fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",MIPS_DECODE[loop].name);
1099 exit(9);
1100 }
1101
1102 /* If register specified shift, then extract the relevant shift amount: */
1103 if (flags & fieldval('s'))
1104 printf(" op1 &= 0x%02X;\n",(bits - 1));
1105
1106 /* If HI32 specified, then shift range is 32..63 */
1107 if (MIPS_DECODE[loop].flags & HI32)
1108 printf(" op1 |= (1 << 6);\n");
1109
1110 /* We do not need to perform pre-masking with 0xFFFFFFFF when
1111 dealing with 32bit shift lefts, since the sign-extension
1112 code will replace any remaining hi-bits: */
1113 if (MIPS_DECODE[loop].flags & LEFT)
1114 printf(" GPR[destreg] = ((unsigned long long)op2 << op1);\n");
1115 else
1116 printf(" GPR[destreg] = ((unsigned long long)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
1117
1118 /* For ARITHMETIC shifts, we must duplicate the sign-bit */
1119 if (MIPS_DECODE[loop].flags & ARITHMETIC)
1120 printf(" GPR[destreg] |= ((op2 & ((%s)1 << %d)) ? ((((%s)1 << (op1 + 1)) - 1) << (%d - op1)) : 0);\n",ltype,(bits - 1),ltype,(bits - 1));
1121
1122 /* Ensure WORD values are sign-extended into 64bit registers */
1123 if ((bits == 32) && (gprlen == 64))
1124 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
1125 }
1126 break ;
1127
1128 case MOVE:
1129 if (MIPS_DECODE[loop].flags & (HI | LO)) {
1130 char *regname = ((MIPS_DECODE[loop].flags & LO) ? "LO" : "HI");
1131 if (flags & fieldval('d'))
1132 printf(" GPR[destreg] = %s;\n",regname);
1133 else {
1134 if (features & FEATURE_WARN_LOHI) {
1135 printf(" if (%sACCESS != 0)\n",regname);
1136 printf(" WARNING(\"MT (move-to) over-writing %s register value\");\n",regname);
1137 }
1138 printf(" %s = op1;\n",regname);
1139 }
1140 if (features & FEATURE_WARN_LOHI)
1141 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
1142 } else
1143 if (MIPS_DECODE[loop].flags & SHIFT16)
1144 printf(" GPR[destreg] = (op2 << 16);\n");
1145 else {
1146 /* perform conditional move */
1147 if (!(MIPS_DECODE[loop].flags & EQ)) {
1148 fprintf(stderr,"Standard conditional %s does not have the equality flag\n",MIPS_DECODE[loop].name);
1149 exit(8);
1150 }
1151 printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1152 printf(" GPR[destreg] = op1;\n");
1153 }
1154 break ;
1155
1156 case SYNC:
1157 printf(" SyncOperation(op1);\n");
1158 break ;
1159
1160 case SYSCALL:
1161 printf(" SignalException(SystemCall);\n");
1162 break ;
1163
1164 case BREAK:
1165 printf(" SignalException(BreakPoint);\n");
1166 break ;
1167
1168 case TRAP:
1169 {
1170 int boolNOT = (MIPS_DECODE[loop].flags & NOT);
1171 int boolEQ = (MIPS_DECODE[loop].flags & EQ);
1172 int boolGT = (MIPS_DECODE[loop].flags & GT);
1173 int boolLT = (MIPS_DECODE[loop].flags & LT);
1174 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1175
1176 if (boolGT && boolLT) {
1177 fprintf(stderr,"GT and LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1178 exit(8);
1179 }
1180
1181 if (boolNOT && (boolGT || boolLT)) {
1182 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
1183 exit(8);
1184 }
1185
1186 printf(" if ((%slong long)op1 ",(boolU ? "unsigned " : ""));
1187 printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
1188 printf(" (%slong long)op2)\n",(boolU ? "unsigned " : ""));
1189 printf(" SignalException(Trap);\n");
1190 }
1191 break ;
1192
1193 case SET:
1194 {
1195 int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
1196
1197 if (!(MIPS_DECODE[loop].flags & LT)) {
1198 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE[loop].name);
1199 exit(8);
1200 }
1201
1202 printf(" if ((%slong long)op1 < (%slong long)op2)\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
1203 printf(" GPR[destreg] = 1;\n");
1204 printf(" else\n");
1205 printf(" GPR[destreg] = 0;\n");
1206 }
1207 break ;
1208
1209 case AND:
1210 printf(" GPR[destreg] = (op1 & op2);\n");
1211 break ;
1212
1213 case OR:
1214 printf(" GPR[destreg] = (%sop1 | op2);\n",((MIPS_DECODE[loop].flags & NOT) ? "~" : ""));
1215 break ;
1216
1217 case XOR:
1218 printf(" GPR[destreg] = (op1 ^ op2);\n");
1219 break ;
1220
1221 case DECODE:
1222 printf(" decode_coproc(instruction);\n");
1223 break ;
1224
1225 case CACHE:
1226 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1227 /* The virtual address is translated to a physical address using the TLB */
1228 /* The hint specifies a cache operation for that address */
1229 printf(" uword64 vaddr = (op1 + offset);\n");
1230 printf(" uword64 paddr;\n");
1231 printf(" int uncached;\n");
1232 /* NOTE: We are assuming that the AddressTranslation is a load: */
1233 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1234 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1235 break;
1236
1237 case MADD16: /* VR4100 specific multiply-add instructions */
1238 /* Some of this code is shared with the standard multiply
1239 routines, so an effort should be made to merge where
1240 possible. */
1241 if (features & FEATURE_WARN_LOHI) {
1242 printf(" CHECKHILO(\"Multiply-Add\");\n");
1243 }
1244 if (features & FEATURE_WARN_RESULT) {
1245 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1246 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1247 printf(" WARNING(\"MADD16 operation with non-16bit operands\");\n");
1248 }
1249 printf(" {\n");
1250 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1251 if (GETDATASIZE() == DOUBLEWORD) {
1252 printf(" LO = LO + temp;\n");
1253 } else { /* WORD */
1254 printf(" temp += (((HI&0xFFFFFFFF) << 32) | (LO & 0xFFFFFFFF));\n");
1255 printf(" LO = SIGNEXTEND((%s)(temp & 0xFFFFFFFF),32);\n",regtype);
1256 printf(" HI = SIGNEXTEND((%s)((temp >> 32) & 0xFFFFFFFF),32);\n",regtype);
1257 }
1258 printf(" }\n");
1259 break;
1260
1261 case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1262 if (doisa < 4) {
1263 printf(" if (CoProcPresent(3))\n");
1264 printf(" SignalException(CoProcessorUnusable);\n");
1265 printf(" else\n");
1266 }
1267 printf(" SignalException(ReservedInstruction,instruction);\n");
1268 break ;
1269
1270 case JUMP:
1271 if (MIPS_DECODE[loop].flags & LINK) {
1272 if (!(MIPS_DECODE[loop].flags & REG))
1273 printf(" int destreg = 31;\n");
1274 printf(" GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */\n");
1275 }
1276
1277 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1278 printf(" DSPC = op1;\n");
1279 printf(" DELAYSLOT();\n");
1280 break ;
1281
1282 case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1283 if (MIPS_DECODE[loop].flags & FP) {
1284 if (doisa < 4) {
1285 printf(" if (condition_code != 0)\n");
1286 printf(" SignalException(ReservedInstruction,instruction);\n");
1287 printf(" else {\n");
1288 }
1289 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
1290 printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
1291 } else {
1292 if ((MIPS_DECODE[loop].flags & NOT) && !(MIPS_DECODE[loop].flags & EQ)) {
1293 fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",MIPS_DECODE[loop].name);
1294 exit(7);
1295 }
1296 if ((MIPS_DECODE[loop].flags & NOT) && (MIPS_DECODE[loop].flags & (GT | LT))) {
1297 fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",MIPS_DECODE[loop].name);
1298 exit(7);
1299 }
1300 /* GT LT */
1301 if (MIPS_DECODE[loop].flags & GT)
1302 printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1303 else
1304 if (MIPS_DECODE[loop].flags & LT)
1305 printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
1306 else
1307 if (MIPS_DECODE[loop].flags & EQ)
1308 printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1309 }
1310
1311 if (MIPS_DECODE[loop].flags & LINK) {
1312 if (features & FEATURE_WARN_R31) {
1313 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS);
1314 printf(" WARNING(\"Branch with link using r31 as source operand\");\n");
1315 }
1316 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1317 }
1318
1319 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1320 printf(" if (condition) {\n");
1321 printf(" DSPC = (PC + offset);\n");
1322 printf(" DELAYSLOT();\n");
1323 printf(" }\n");
1324 if ((MIPS_DECODE[loop].flags & FP) && (doisa != 1)) {
1325 printf(" else if (likely) {\n");
1326 printf(" NULLIFY();\n");
1327 printf(" }\n");
1328 } else if (MIPS_DECODE[loop].flags & LIKELY) {
1329 printf(" else\n");
1330 printf(" NULLIFY();\n");
1331 }
1332 if ((MIPS_DECODE[loop].flags & FP) && (doisa < 4))
1333 printf(" }\n");
1334 break ;
1335
1336 case PREFETCH: /* The beginning is shared with normal load operations */
1337 case LOAD:
1338 case STORE:
1339 {
1340 int isload = ((MIPS_DECODE[loop].type == LOAD) || (MIPS_DECODE[loop].type == PREFETCH));
1341 int datalen;
1342 char *accesslength = "<UNKNOWN>";
1343
1344 switch (GETDATASIZE()) {
1345 case BYTE :
1346 datalen = 1;
1347 accesslength = "AccessLength_BYTE";
1348 break ;
1349
1350 case HALFWORD :
1351 datalen = 2;
1352 accesslength = "AccessLength_HALFWORD";
1353 break ;
1354
1355 case WORD :
1356 datalen = 4;
1357 accesslength = "AccessLength_WORD";
1358 break ;
1359
1360 case DOUBLEWORD :
1361 datalen = 8;
1362 accesslength = "AccessLength_DOUBLEWORD";
1363 break ;
1364 }
1365
1366 if (MIPS_DECODE[loop].flags & REG)
1367 printf(" uword64 vaddr = ((unsigned long long)op1 + op2);\n");
1368 else
1369 printf(" uword64 vaddr = ((unsigned long long)op1 + offset);\n");
1370 printf(" uword64 paddr;\n");
1371 printf(" int uncached;\n");
1372
1373 /* The following check should only occur on normal (non-shifted) memory loads */
1374 if ((datalen != 1) && !(MIPS_DECODE[loop].flags & (LEFT | RIGHT))) {
1375 printf(" if ((vaddr & %d) != 0)\n",(datalen - 1));
1376 printf(" SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
1377 printf(" else\n") ;
1378 }
1379
1380 printf(" {\n");
1381 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
1382
1383 if (MIPS_DECODE[loop].type == PREFETCH)
1384 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1385 else {
1386 printf(" {\n");
1387 printf(" %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
1388
1389 if ((MIPS_DECODE[loop].flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
1390 fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
1391 exit(6);
1392 }
1393
1394 if (MIPS_DECODE[loop].flags & (LEFT | RIGHT)) {
1395 if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & RIGHT)) {
1396 fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",MIPS_DECODE[loop].name);
1397 exit(4);
1398 }
1399
1400 switch (datalen) {
1401 case 8:
1402 if (!proc64) {
1403 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE[loop].name);
1404 exit(4);
1405 }
1406 /* fall through to... */
1407 case 4:
1408 {
1409 char *maskstr = ((datalen == 8) ? "((uword64)-1)" : "0xFFFFFFFF");
1410
1411 printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
1412 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
1413 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
1414 printf(" int byte;\n");
1415 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
1416 printf(" byte = ((vaddr & mask) ^ bigend);\n");
1417 printf(" if (%sBigEndianMem)\n",((MIPS_DECODE[loop].flags & LEFT) ? "!" : ""));
1418 printf(" paddr &= ~mask;\n");
1419
1420 if (isload) {
1421 if (MIPS_DECODE[loop].flags & LEFT)
1422 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
1423 else
1424 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
1425 }
1426
1427 if (MIPS_DECODE[loop].flags & LEFT) {
1428 if (isload) {
1429 /* For WORD transfers work out if the value will
1430 be in the top or bottom of the DOUBLEWORD
1431 returned: */
1432 if (proc64 && (datalen == 4)) {
1433 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1434 printf(" memval >>= 32;\n");
1435 printf(" }\n");
1436 }
1437 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
1438 if (proc64 && (datalen == 4))
1439 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1440 } else { /* store */
1441 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
1442 /* TODO: This is duplicated in the LOAD code
1443 above - and the RIGHT LOAD and STORE code
1444 below. It should be merged if possible. */
1445 if (proc64 && (datalen == 4)) {
1446 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1447 printf(" memval <<= 32;\n");
1448 printf(" }\n");
1449 }
1450 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
1451 }
1452 } else { /* RIGHT */
1453 if (isload) {
1454 if (proc64 && (datalen == 4)) {
1455 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
1456 printf(" memval >>= 32;\n");
1457 printf(" }\n");
1458 }
1459 printf(" {\n");
1460 printf(" uword64 srcmask;\n");
1461 /* All of this extra code is just a bodge
1462 required because some hosts don't allow
1463 ((v) << 64). The SPARC just leaves the (v)
1464 value un-touched. */
1465 printf(" if (byte == 0)\n");
1466 printf(" srcmask = 0;\n");
1467 printf(" else\n");
1468 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
1469 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen);
1470 printf(" }\n");
1471 if (proc64 && (datalen == 4))
1472 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
1473 } else { /* store */
1474 printf(" memval = (op2 << (byte * 8));\n");
1475 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength);
1476 }
1477 }
1478 }
1479 break;
1480
1481 default:
1482 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
1483 exit(6);
1484 }
1485 } else { /* normal memory transfer */
1486 if (((datalen == 8) || ((datalen == 4) & (MIPS_DECODE[loop].flags & UNSIGNED))) && !proc64) {
1487 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",MIPS_DECODE[loop].name);
1488 exit(4);
1489 /* TODO: The R4000 documentation states that a LWU
1490 instruction executed when in a 32bit processor mode
1491 should cause a ReservedInstruction exception. This
1492 will mean adding a run-time check into the code
1493 sequence. */
1494 }
1495
1496 if (isload) {
1497 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
1498 printf(" unsigned int shift = %d;\n",(datalen >> 1));
1499 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1500 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1501 printf(" unsigned int byte;\n");
1502
1503 if (datalen != 8) /* not for DOUBLEWORD */
1504 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1505
1506 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
1507
1508 /* The following will only make sense if the
1509 "LoadMemory" above returns a DOUBLEWORD entity */
1510 if (datalen != 8) { /* not for DOUBLEWORD */
1511 int valmask;
1512 switch (datalen) {
1513 case 1:
1514 valmask = 0xFF;
1515 break;
1516
1517 case 2:
1518 valmask = 0xFFFF;
1519 break;
1520
1521 case 4:
1522 valmask = 0xFFFFFFFF;
1523 break;
1524
1525 default:
1526 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,MIPS_DECODE[loop].name);
1527 exit(4);
1528 }
1529 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1530 /* NOTE: The R4000 user manual has the COP_LW
1531 occuring in the same cycle as the rest of the
1532 instruction, yet the MIPS IV shows the operation
1533 happening on the next cycle. To keep the simulator
1534 simple, this code follows the R4000
1535 manual. Experimentation with a silicon
1536 implementation will be needed to ascertain the
1537 correct operation. */
1538 if (MIPS_DECODE[loop].flags & COPROC)
1539 printf(" COP_LW(((instruction >> 26) & 0x3),destreg,(unsigned int)");
1540 else
1541 printf(" GPR[destreg] = (");
1542
1543 if (MIPS_DECODE[loop].flags & SIGNEXTEND)
1544 printf("SIGNEXTEND(");
1545 printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
1546 if (MIPS_DECODE[loop].flags & SIGNEXTEND)
1547 printf(",%d)",(datalen * 8));
1548 printf(");\n");
1549 } else {
1550 if (MIPS_DECODE[loop].flags & COPROC)
1551 printf(" COP_LD(((instruction >> 26) & 0x3),destreg,memval);;\n");
1552 else
1553 printf(" GPR[destreg] = memval;\n");
1554 }
1555 } else { /* store operation */
1556 if ((datalen == 1) || (datalen == 2)) {
1557 /* SH and SB */
1558 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
1559 printf(" unsigned int shift = %d;\n",(datalen >> 1));
1560 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
1561 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
1562 printf(" unsigned int byte;\n");
1563
1564 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
1565 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
1566 printf(" memval = (op2 << (8 * byte));\n");
1567 } else
1568 if (proc64 && (datalen == 4)) { /* proc64 SC and SW */
1569 printf(" unsigned int byte;\n");
1570 printf(" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (ReverseEndian << 2)));\n");
1571 printf(" byte = ((vaddr & 0x7) ^ (BigEndianCPU << 2));\n");
1572 if (MIPS_DECODE[loop].flags & COPROC)
1573 printf(" memval = (((unsigned long long)COP_SW(((instruction >> 26) & 0x3),%s)) << (8 * byte));\n",((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg"));
1574 else
1575 printf(" memval = (op2 << (8 * byte));\n");
1576 } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
1577 if (MIPS_DECODE[loop].flags & COPROC)
1578 printf(" memval = (unsigned long long)COP_S%c(((instruction >> 26) & 0x3),%s);\n",((datalen == 8) ? 'D' : 'W'),((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg"));
1579 else
1580 printf(" memval = op2;\n");
1581 }
1582
1583 if (MIPS_DECODE[loop].flags & ATOMIC)
1584 printf(" if (LLBIT)\n");
1585
1586 printf(" {\n");
1587 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
1588 printf(" }\n");
1589 }
1590
1591 if (MIPS_DECODE[loop].flags & ATOMIC) {
1592 if ((datalen != 4) && (datalen != 8)) {
1593 fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",MIPS_DECODE[loop].name);
1594 exit(4);
1595 } else
1596 if (isload)
1597 printf(" LLBIT = 1;\n");
1598 else {
1599 /* The documentation states that:
1600
1601 SC *WILL* fail if coherent store into the same
1602 block occurs, or if an exception occurs between
1603 the LL and SC instructions.
1604
1605 SC *MAY* fail if a load, store or prefetch is
1606 executed on the processor (VR4300 doesn't seem
1607 to), or if the instructions between the LL and
1608 SC are not in a 2048byte contiguous VM range.
1609
1610 SC *MUST* have been preceded by an LL
1611 (i.e. LLBIT will be set), and it must use the
1612 same Vaddr, Paddr and cache-coherence algorithm
1613 as the LL (which means we should store this
1614 information from the load-conditional).
1615 */
1616 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
1617 }
1618 }
1619 }
1620 printf(" }\n");
1621 }
1622 printf(" }\n");
1623 }
1624 break ;
1625
1626 case FPPREFX:
1627 /* This code could be merged with the PREFIX generation above: */
1628 printf(" uword64 vaddr = ((unsigned long long)op1 + (unsigned long long)op2);\n");
1629 printf(" uword64 paddr;\n");
1630 printf(" int uncached;\n");
1631 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1632 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
1633 break ;
1634
1635 case FPMOVEC:
1636 if (MIPS_DECODE[loop].flags & CONTROL) {
1637 /* The following "magic" of interpreting the FP
1638 control-register number would not be needed if we were not
1639 trying to match our internal register numbers with those
1640 used by GDB. */
1641 printf(" if (to) {\n");
1642 if (doisa < 4) {
1643 printf(" if (fs == 0) {\n");
1644 printf(" PENDING_FILL((fs + FCR0IDX),(GPR[ft]&0xFFFFFFFF));\n");
1645 printf(" } else if (fs == 31) {\n");
1646 printf(" PENDING_FILL((fs + FCR31IDX),(GPR[ft]&0xFFFFFFFF));\n");
1647 printf(" } /* else NOP */\n");
1648 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
1649 } else {
1650 printf(" if (fs == 0) {\n");
1651 printf(" FCR0 = (GPR[ft] & 0xFFFFFFFF);\n");
1652 printf(" } else if (fs == 31) {\n");
1653 printf(" FCR31 = (GPR[ft] & 0xFFFFFFFF);\n");
1654 printf(" } /* else NOP */\n");
1655 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
1656 }
1657 printf(" } else { /* control from */\n");
1658 if (doisa < 4) {
1659 printf(" if (fs == 0) {\n");
1660 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
1661 printf(" } else if (fs == 31) {\n");
1662 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
1663 printf(" } /* else NOP */\n");
1664 } else {
1665 printf(" if (fs == 0) {\n");
1666 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
1667 printf(" } else if (fs == 31) {\n");
1668 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
1669 printf(" } /* else NOP */\n");
1670 }
1671 printf(" }\n");
1672 } else {
1673 printf(" if (to) {\n");
1674 if (GETDATASIZE() == WORD) {
1675 if (doisa < 4) {
1676 printf(" if (SizeFGR() == 64) {\n");
1677 printf(" PENDING_FILL((fs + FGRIDX),((unsigned long long)((unsigned long long)0xDEADC0DE << 32) | (GPR[ft]&0xFFFFFFFF)));\n");
1678 printf(" } else { \n");
1679 printf(" PENDING_FILL((fs + FGRIDX),(GPR[ft]&0xFFFFFFFF));\n");
1680 printf(" }\n");
1681 } else {
1682 printf(" if (SizeFGR() == 64)\n");
1683 printf(" FGR[fs] = ((unsigned long long)((unsigned long long)0xDEADC0DE << 32) | (GPR[ft] & 0xFFFFFFFF));\n");
1684 printf(" else\n");
1685 printf(" FGR[fs] = (GPR[ft] & 0xFFFFFFFF);\n");
1686 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1687 }
1688 } else if (GETDATASIZE() == DOUBLEWORD) {
1689 if (doisa < 4) {
1690 printf(" if (SizeFGR() == 64) {\n");
1691 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
1692 printf(" } else\n");
1693 printf(" if ((fs & 0x1) == 0)\n");
1694 printf(" {\n");
1695 printf(" PENDING_FILL(((fs + 1) + FGRIDX),(GPR[ft]>>32));\n");
1696 printf(" PENDING_FILL((fs + FGRIDX),(GPR[ft]&0xFFFFFFFF));\n");
1697 printf(" }\n");
1698 if (features & FEATURE_WARN_RESULT) {
1699 printf(" else\n");
1700 printf(" UndefinedResult();\n");
1701 }
1702 } else {
1703 printf(" if (SizeFGR() == 64) {\n");
1704 printf(" FGR[fs] = GPR[ft];\n");
1705 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1706 printf(" } else\n");
1707 printf(" if ((fs & 0x1) == 0)\n");
1708 printf(" {\n");
1709 printf(" FGR[fs + 1] = (GPR[ft] >> 32);\n");
1710 printf(" FGR[fs] = (GPR[ft] & 0xFFFFFFFF);\n");
1711 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
1712 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
1713 printf(" }\n");
1714 if (features & FEATURE_WARN_RESULT) {
1715 printf(" else\n");
1716 printf(" UndefinedResult();\n");
1717 }
1718 }
1719 } else {
1720 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
1721 exit(1);
1722 }
1723 printf(" } else {\n");
1724 if (GETDATASIZE() == WORD) {
1725 if (doisa < 4) /* write-back occurs in next cycle */
1726 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
1727 else /* in this cycle */
1728 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
1729 } else if (GETDATASIZE() == DOUBLEWORD) {
1730 if (doisa < 4) {
1731 printf(" if (SizeFGR() == 64) {\n");
1732 printf(" PENDING_FILL(ft,FGR[fs]);\n");
1733 printf(" } else\n");
1734 printf(" if ((fs & 0x1) == 0) {\n");
1735 printf(" PENDING_FILL(ft,((FGR[fs+1]<<32)|FGR[fs]));\n");
1736 printf(" } else {\n");
1737 printf(" PENDING_FILL(ft,((unsigned long long)0xDEADC0DE << 32) | 0xBAD0BAD0);\n");
1738 if (features & FEATURE_WARN_RESULT)
1739 printf(" UndefinedResult();\n");
1740 printf(" }\n");
1741 } else {
1742 printf(" if (SizeFGR() == 64)\n");
1743 printf(" GPR[ft] = FGR[fs];\n");
1744 printf(" else\n");
1745 printf(" if ((fs & 0x1) == 0)\n");
1746 printf(" GPR[ft] = ((FGR[fs + 1] << 32) | FGR[fs]);\n");
1747 printf(" else {\n");
1748 printf(" GPR[ft] = (((unsigned long long)0xDEADC0DE << 32) | 0xBAD0BAD0);\n");
1749 if (features & FEATURE_WARN_RESULT)
1750 printf(" UndefinedResult();\n");
1751 printf(" }\n");
1752 }
1753 } else {
1754 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
1755 exit(1);
1756 }
1757 printf(" }\n");
1758 }
1759 break ;
1760
1761 case FPMOVE:
1762 if (MIPS_DECODE[loop].flags & CONDITIONAL) {
1763 if (MIPS_DECODE[loop].flags & INTEGER) { /* moving GPR - testing FGR */
1764 printf(" if (GETFCC(condition_code) == boolean)\n");
1765 printf(" GPR[destreg] = op1;\n");
1766 } else {
1767 if (MIPS_DECODE[loop].flags & EQ) /* moving FGR - testing GPR */
1768 printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
1769 else
1770 printf(" if (GETFCC(condition_code) == boolean)\n");
1771 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1772 printf(" else\n");
1773 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
1774 }
1775 } else { /* simple MOVE */
1776 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
1777 }
1778 break ;
1779
1780 case FPNEG:
1781 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1782 printf(" SignalException(ReservedInstruction,instruction);\n");
1783 printf(" else\n");
1784 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
1785 break ;
1786
1787 case FPABS:
1788 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1789 printf(" SignalException(ReservedInstruction,instruction);\n");
1790 printf(" else\n");
1791 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
1792 break ;
1793
1794 case FPDIV:
1795 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1796 printf(" SignalException(ReservedInstruction,instruction);\n");
1797 printf(" else\n");
1798 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1799 break ;
1800
1801 case FPMUL:
1802 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1803 printf(" SignalException(ReservedInstruction,instruction);\n");
1804 printf(" else\n");
1805 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1806 break ;
1807
1808 case FPRECIP:
1809 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1810 printf(" SignalException(ReservedInstruction,instruction);\n");
1811 printf(" else\n");
1812 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
1813 break ;
1814
1815 case FPSQRT:
1816 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1817 printf(" SignalException(ReservedInstruction,instruction);\n");
1818 printf(" else\n");
1819 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((MIPS_DECODE[loop].flags & RECIP) ? "Recip" : ""));
1820 break ;
1821
1822 case FPCEIL:
1823 case FPFLOOR:
1824 case FPTRUNC:
1825 case FPROUND:
1826 {
1827 char *op = "";
1828 char *type = "";
1829
1830 switch (MIPS_DECODE[loop].type) {
1831 case FPCEIL:
1832 op = "FP_RM_TOPINF";
1833 break;
1834 case FPFLOOR:
1835 op = "FP_RM_TOMINF";
1836 break;
1837 case FPTRUNC:
1838 op = "FP_RM_TOZERO";
1839 break;
1840 case FPROUND:
1841 op = "FP_RM_NEAREST";
1842 break;
1843 default:
1844 fprintf(stderr,"Error: Handled missing for FP reason code %d\n",MIPS_DECODE[loop].type);
1845 exit(1);
1846 }
1847
1848 switch (GETDATASIZE()) {
1849 case WORD :
1850 type = "fmt_word";
1851 break;
1852 case DOUBLEWORD :
1853 type = "fmt_long";
1854 break;
1855 default:
1856 fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
1857 exit(1);
1858 }
1859 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1860 printf(" SignalException(ReservedInstruction,instruction);\n");
1861 printf(" else\n");
1862 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
1863 }
1864 break ;
1865
1866 case FPCONVERT:
1867 {
1868 char *type = "";
1869 switch (GETDATASIZE()) {
1870 case SINGLE:
1871 type = "fmt_single";
1872 break;
1873 case DOUBLE:
1874 type = "fmt_double";
1875 break;
1876 case WORD:
1877 type = "fmt_word";
1878 break;
1879 case DOUBLEWORD:
1880 type = "fmt_long";
1881 break;
1882 default :
1883 fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZE());
1884 exit(1);
1885 }
1886
1887 /* Not all combinations of conversion are valid at the
1888 moment: When converting to a fixed-point format, only
1889 floating-point sources are allowed. */
1890 printf(" if ((format == %s) | %s)\n",type,((MIPS_DECODE[loop].flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
1891 printf(" SignalException(ReservedInstruction,instruction);\n");
1892 printf(" else\n");
1893 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
1894 }
1895 break ;
1896
1897 case FPSUB:
1898 if (MIPS_DECODE[loop].flags & MULTIPLY) {
1899 char *type = "";
1900 switch (GETDATASIZE()) {
1901 case SINGLE:
1902 type = "fmt_single";
1903 break;
1904 case DOUBLE:
1905 type = "fmt_double";
1906 break;
1907 default:
1908 fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZE());
1909 exit(1);
1910 }
1911 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);
1912 } else {
1913 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1914 printf(" SignalException(ReservedInstruction,instruction);\n");
1915 printf(" else\n");
1916 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1917 }
1918 break ;
1919
1920 case FPADD:
1921 if (MIPS_DECODE[loop].flags & MULTIPLY) {
1922 char *type = "";
1923 switch (GETDATASIZE()) {
1924 case SINGLE:
1925 type = "fmt_single";
1926 break;
1927 case DOUBLE:
1928 type = "fmt_double";
1929 break;
1930 default:
1931 fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
1932 exit(1);
1933 }
1934 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);
1935 } else {
1936 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1937 printf(" SignalException(ReservedInstruction,instruction);\n");
1938 printf(" else\n");
1939 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
1940 }
1941 break ;
1942
1943 case FPCOMPARE:
1944 /* For the MIPS I,II or III there *MUST* be at least one
1945 instruction between the compare that sets a condition code
1946 and the branch that tests it. NOTE: However the hardware
1947 does not detect this condition. */
1948 /* Explicitly limit the operation to S and D formats: */
1949 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
1950 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1951 printf(" else {\n");
1952 if (doisa < 4) {
1953 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
1954 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1955 printf(" else\n");
1956 }
1957 printf(" {\n");
1958 printf(" int ignore = 0;\n");
1959 printf(" int less = 0;\n");
1960 printf(" int equal = 0;\n");
1961 printf(" int unordered = 1;\n");
1962 printf(" unsigned long long ofs = ValueFPR(fs,format);\n");
1963 printf(" unsigned long long oft = ValueFPR(ft,format);\n");
1964 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
1965 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
1966 printf(" FCSR |= FP_CAUSE(IO);\n");
1967 printf(" SignalException(FPE);\n");
1968 printf(" ignore = 1;\n");
1969 printf(" }\n");
1970 printf(" } else {\n");
1971 printf(" less = Less(ofs,oft,format);\n");
1972 printf(" equal = Equal(ofs,oft,format);\n");
1973 printf(" unordered = 0;\n");
1974 printf(" }\n");
1975 printf(" if (!ignore) {\n");
1976 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
1977 printf(" SETFCC(condition_code,condition);\n");
1978 printf(" }\n");
1979 printf(" }\n");
1980 printf(" }\n");
1981 break ;
1982
1983 default:
1984 fprintf(stderr,"Unrecognised opcode type %d\n",MIPS_DECODE[loop].type) ;
1985 exit(6) ;
1986 }
1987 printf(" }\n") ;
1988 printf(" }\n") ;
1989 printf(" break ;\n") ;
1990 }
1991 }
1992
1993 printf("default : /* Unrecognised instruction */\n") ;
1994 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1995 printf(" break ;\n") ;
1996 printf("}\n}\n") ;
1997 printf("#endif /* simulator engine */\n");
1998
1999 return ;
2000 }
2001
2002 /*---------------------------------------------------------------------------*/
2003
2004 /* The command-line feature controls are presented in a similar style
2005 to those offered by GCC, in the aim of providing a consistent
2006 interface to the user. */
2007 typedef enum {
2008 T_NONE, /* no argument - mask and value fields control "feature" definition */
2009 T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
2010 T_STRING /* string argument - optionally prcededed by '=' */
2011 } mactypes;
2012
2013 struct {
2014 char *name;
2015 mactypes type;
2016 unsigned int mask;
2017 unsigned int value;
2018 char *desc;
2019 } machine_options[] = {
2020 {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"},
2021 {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"},
2022 {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"},
2023 {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"},
2024 {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"},
2025 {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"},
2026 {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"},
2027 {0, T_NONE, 0,0}
2028 };
2029
2030 /* The following architecture identies are those accepted by the "-mcpu" option: */
2031 struct architectures {
2032 const char *name; /* ASCII string identifier for command-line, no white-space allowed */
2033 unsigned int idflag; /* or-ed into "isa" value */
2034 };
2035
2036 static const struct architectures available_architectures[] = {
2037 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
2038 {0, 0} /* terminator */
2039 };
2040
2041 /*---------------------------------------------------------------------------*/
2042
2043 static void
2044 usage(name)
2045 char *name;
2046 {
2047 int loop;
2048
2049 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
2050
2051 fprintf(stderr,"\
2052 The output of this program is a block of 'C' code designed to be\n\
2053 included into the main simulation control loop of a device specific\n\
2054 simulator.\n");
2055
2056 fprintf(stderr,"\nOptions:\n");
2057 fprintf(stderr," -h --help\t\tProvide this help text\n");
2058 fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
2059 fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n");
2060
2061 for (loop = 0; (machine_options[loop].name != 0); loop++) {
2062 fprintf(stderr," -m%s",machine_options[loop].name);
2063 switch (machine_options[loop].type) {
2064 case T_NUM :
2065 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
2066 case T_NONE :
2067 break;
2068
2069 case T_STRING :
2070 fprintf(stderr,"=name");
2071 break;
2072
2073 default :
2074 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options[loop].type);
2075 exit(1);
2076 }
2077 fprintf(stderr,"%s\n",machine_options[loop].desc);
2078 }
2079
2080 fprintf(stderr,"\nAvailable \"-mcpu\" architectures: ");
2081 for (loop = 0; (available_architectures[loop].name != 0); loop++)
2082 fprintf(stderr,"%s ",available_architectures[loop].name);
2083 fprintf(stderr,"\n\n");
2084
2085 fprintf(stderr,"\
2086 The \"trace\" and \"warnings\" options do not define the output stream.\n\
2087 They only inform the code that includes the constructed engine to provide\n\
2088 the required features.\n\n\
2089 The \"-mips0\" option forces the construction of a simulator supporting\n\
2090 the highest available MIPS ISA supported.\n");
2091
2092 return;
2093 }
2094
2095 /*---------------------------------------------------------------------------*/
2096
2097 int
2098 main(argc,argv)
2099 int argc;
2100 char **argv;
2101 {
2102 int c;
2103 char *progname = argv[0];
2104 unsigned int doarch = DEF_ISA;
2105 unsigned int features = 0; /* default state */
2106
2107 if (DEF_FP)
2108 features |= FEATURE_HASFPU;
2109 if (!DEF_PROC64)
2110 features |= FEATURE_PROC32;
2111 if (DEF_FPSINGLE)
2112 features |= FEATURE_FPSINGLE;
2113
2114 if (features & FEATURE_PROC32)
2115 features &= ~FEATURE_GP64;
2116 else
2117 features |= FEATURE_GP64;
2118
2119 while (1) {
2120 int this_option_optind = (optind ? optind : 1);
2121 int option_index = 0;
2122 static struct option cmdline[] = {
2123 {"fast", 0,0,'f'},
2124 {"help", 0,0,'h'},
2125 {"warnings",0,0,'w'},
2126 {0, 0,0,0}
2127 };
2128
2129 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
2130 if (c == -1)
2131 break ; /* out of the while loop */
2132
2133 switch (c) {
2134 case 'h' : /* help */
2135 usage(progname);
2136 exit(0);
2137
2138 case 'f' : /* fast */
2139 features |= FEATURE_FAST;
2140 break;
2141
2142 case 'w' : /* warnings */
2143 features |= FEATURE_WARNINGS;
2144 /* TODO: Future extension: Allow better control over the warnings generated:
2145 disable warnings -wnone ~FEATURE_WARNINGS
2146 all possible warnings -wall FEATURE_WARNINGS
2147 pipeline stall occuring -wstall FEATURE_WARN_STALL
2148 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
2149 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
2150 bad r31 use -wr31 FEATURE_WARN_R31
2151 undefined results -wresult FEATURE_WARN_RESULT
2152 */
2153 break;
2154
2155 case 'm' : /* machine options */
2156 {
2157 int loop;
2158
2159 for (loop = 0; (machine_options[loop].name != 0); loop++)
2160 if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) {
2161 char *loptarg = (optarg + strlen(machine_options[loop].name));
2162 switch (machine_options[loop].type) {
2163 case T_NONE :
2164 if (*loptarg) {
2165 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
2166 exit(1);
2167 }
2168 features &= ~(machine_options[loop].mask);
2169 features |= machine_options[loop].value;
2170 break;
2171
2172 case T_NUM :
2173 if (*loptarg && *loptarg == '=')
2174 loptarg++;
2175
2176 if (strcmp(machine_options[loop].name,"ips") == 0) {
2177 unsigned int num;
2178
2179 if (!*loptarg) {
2180 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
2181 exit(1);
2182 }
2183
2184 num = strtoul(loptarg,&loptarg,10);
2185
2186 if ((num == ULONG_MAX) && (errno = ERANGE)) {
2187 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
2188 exit(1);
2189 }
2190
2191 if (*loptarg) {
2192 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
2193 exit(1);
2194 }
2195
2196 if (num > MASK_ISA) {
2197 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
2198 exit(1);
2199 }
2200
2201 doarch = ((doarch & ~MASK_ISA) | num);
2202 if ((num == 0) || (num > 2)) {
2203 if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64))
2204 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num);
2205 features |= FEATURE_GP64;
2206 features &= ~FEATURE_PROC32;
2207 } else {
2208 if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64))
2209 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num);
2210 features &= ~FEATURE_GP64;
2211 features |= FEATURE_PROC32;
2212 }
2213 } else {
2214 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
2215 exit(1);
2216 }
2217 break;
2218
2219 case T_STRING :
2220 if (*loptarg && *loptarg == '=')
2221 loptarg++;
2222
2223 if (strcmp(machine_options[loop].name,"cpu") == 0) {
2224 int archloop;
2225
2226 if (!*loptarg) {
2227 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
2228 exit(1);
2229 }
2230
2231 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
2232 if ((*loptarg == 'v') || (*loptarg == 'V'))
2233 *loptarg++;
2234
2235 if (*loptarg && (*loptarg == 'r') || (*loptarg == 'R'))
2236 *loptarg++;
2237
2238 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
2239 doarch |= available_architectures[archloop].idflag;
2240 break;
2241 }
2242 }
2243
2244 if (available_architectures[archloop].name == 0) {
2245 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
2246 exit(1);
2247 }
2248 } else {
2249 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
2250 exit(1);
2251 }
2252 break;
2253
2254 default :
2255 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
2256 exit(1);
2257 }
2258 break;
2259 }
2260
2261 if (machine_options[loop].name == 0) {
2262 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
2263 exit(1);
2264 }
2265 }
2266 break;
2267
2268 case '?' :
2269 /* An error message should already have been displayed */
2270 exit(1);
2271
2272 default :
2273 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
2274 exit(1);
2275 }
2276 }
2277
2278 if (optind < argc) {
2279 fprintf(stderr,"%s: Spurios non-option arguments ",progname);
2280 while (optind < argc)
2281 fprintf(stderr,"\"%s\" ",argv[optind++]);
2282 fprintf(stderr,"\n");
2283 exit(1);
2284 }
2285
2286 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
2287 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
2288
2289 process_instructions(doarch,features) ;
2290 return(0) ;
2291 }
2292
2293 /*---------------------------------------------------------------------------*/
2294 /*> EOF gencode.c <*/
This page took 0.101172 seconds and 5 git commands to generate.