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