Mon Dec 16 13:39:03 1996 Martin M. Hunt <hunt@pizza.cygnus.com>
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
CommitLineData
8ad57737 1/*> gencode.c <*/
a647a859
JSC
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*/
8ad57737
JSC
20
21#if 0
22#define DEBUG (1) /* Just for testing */
23#endif
24
8ad57737
JSC
25/* All output sent to stdout is for the simulator engine. All program
26 related warnings and errors should be sent to stderr. */
27
28/* The simulator decode table is constructed this way to allow the
29 minimal code required for a particular instruction type to be
30 coded. This avoids a large simulator source file, with lots of
31 build-time conditionals controlling what code is included. However
32 this two-stage process does mean that care must be taken to ensure
33 that the correct decoding source is generated for a particular MIPS
34 simulator. */
35
36/* Notes:
37
38 We could provide pipeline modelling by splitting the simulation of
39 instructions into seperate bytecodes for each pipeline
40 stage. e.g. for the VR4300 each instruction would generate 5
41 bytecodes, one for each pipeline stage. The simulator control would
42 then insert these into the relevant pipeline slots, and execute a
43 complete slots worth of bytecodes. However, the shape of the
44 pipeline, and what parts of each instruction are executed in each
45 pipeline stage, are different between MIPS implementations. If we
46 were to construct a simulator for a particular MIPS architecture
47 this would be a good solution.
48
49 To avoid having to provide multiple different pipeline models, a
50 simple approach for dealing with the delay slots, and register
51 dependencies has been used. The "MIPS IV Instruction Set" document
52 (Revision 3.1 - January 1995) details the standard MIPS instruction
53 set, and it defines operations in instruction (not pipe-line)
54 cycles. This means we only need to worry about a few cases where
55 the result is not available until after the next instruction, or
56 where registers in the previous two instruction cycles may be
57 corrupted. The case for corruption only occurs with HI or LO
58 register access, so we can just keep a count within the engine for
59 upto two cycles before marking the register as safe. We then only
60 need to check the safety flag when performing an update that
61 involves the HI or LO register. The only other case is the
62 BC1F/BC1T instructions in the FP unit. For ISAs I, II and III there
63 must be an instruction between the FP CMP and the BC1[FT]. We can
64 perform the same instruction cycle count scheme, so we can raise a
65 warning if an attempt is made to access the condition code early
66 (NOTE: The hardware does not interlock on this operation, so the
67 simulator should just raise a warning).
68
69 For the situations where a result is not available until later, we
70 implent a slot to hold pending values. After the PC is incremented,
71 and before the instruction is decoded we can execute the required
72 register update (or remainder of instruction processing). */
73
74/* The FP instruction decoding is also provided by this code. The
75 instructions are marked as "FP" ones so that we can construct a
76 simulator without an FPU if required. Similarly we mark
77 instructions as Single or Double precision, since some MIPS
78 processors only have single precision FP hardware. */
79
80/* NOTE: Ideally all state should be passed as parameters. This allows
81 a single simulator engine to be used for multiple concurrent
82 simulations. More importantly, if a suitably powerful control is in
83 place it will allow speculative simulation, since the context can
84 be saved easily, and then restored after performing some
85 simulation. The down-side is that for certain host architectures it
86 can slow the simulator down (e.g. if globals can be accessed faster
87 than local structures). However, this is not actually the case at
88 the moment. The constructed engine uses direct names (that can be
89 macro definitions). This keeps the engine source smalled (using
90 short-hands), and it also allows the user to control whether they
91 want to use global, or indirected memory locations. i.e. whether
92 they want a single- or multi-threaded simulator engine. */
93
94/* The constructed simulator engine contains manifests for each of the
95 features supported. The code that includes the engine can then
96 discover the available features during its build. This information
97 can be used to control run-time features provided by the final
98 simulator. */
99
100/*---------------------------------------------------------------------------*/
101
102/* Program defaults */
103#define DEF_ISA (3)
104#define DEF_PROC64 (1 == 1)
105#define DEF_FP (1 == 1)
106#define DEF_FPSINGLE (1 == 0)
107
108#define FEATURE_PROC32 (1 << 0) /* 0 = 64bit; 1 = 32bit */
109#define FEATURE_HASFPU (1 << 1) /* 0 = no FPU; 1 = include FPU */
110#define FEATURE_FPSINGLE (1 << 1) /* 0 = double; 1 = single (only used if FEATURE_HASFPU defined) */
111#define FEATURE_GP64 (1 << 2) /* 0 = GPRLEN 32; 1 = GPRLEN 64 */
8ad57737
JSC
112#define FEATURE_FAST (1 << 17) /* 0 = normal; 1 = disable features that slow performance */
113#define FEATURE_WARN_STALL (1 << 24) /* 0 = nothing; 1 = generate warnings when pipeline would stall */
114#define FEATURE_WARN_LOHI (1 << 25) /* 0 = nothing; 1 = generate warnings when LO/HI corrupted */
115#define FEATURE_WARN_ZERO (1 << 26) /* 0 = nothing; 1 = generate warnings if attempt to write register zero */
116#define FEATURE_WARN_MEM (1 << 27) /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
117#define FEATURE_WARN_R31 (1 << 28) /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
118#define FEATURE_WARN_RESULT (1 << 29) /* 0 = nothing; 1 = generate warnings when undefined results may occur */
119
8bae0a0c
JSC
120#if 1
121#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
122#else
8ad57737 123#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
8bae0a0c 124#endif
8ad57737
JSC
125
126/* FEATURE_WARN_STALL */
127/* If MIPS I we want to raise a warning if an attempt is made to
128 access Rn in an instruction immediately following an Rn update
129 "WARNING : Invalid value read". The simulator engine is designed
130 that the previous value is read in such cases, to allow programs
831f59a2 131 that make use of this feature to execute. */
8ad57737
JSC
132/* If MIPS II or later, attempting to read a register before the
133 update has completed will generate a "WARNING : Processor stall"
134 message (since the processor will lock the pipeline until the value
135 becomes available). */
136
137/* FEATURE_WARN_LOHI */
138/* Warn if an attempt is made to read the HI/LO registers before the
139 update has completed, or if an attempt is made to update the
140 registers whilst an update is occurring. */
141
142/* FEATURE_WARN_ZERO */
143/* Notify the user if an attempt is made to use GPR 0 as a destination. */
144
145/* FEATURE_WARN_R31 */
146/* Notify the user if register r31 (the default procedure call return
147 address) is used unwisely. e.g. If r31 is used as the source in a
148 branch-and-link instruction, it would mean that an exception in the
149 delay slot instruction would not allow the branch to be re-started
150 (since r31 will have been overwritten by the link operation during
151 the first execution of the branch). */
152
153/* FEATURE_WARN_RESULT */
154/* Certain instructions do not raise exceptions when invalid operands
155 are given, they will just result in undefined values being
156 generated. This option controls whether the simulator flags such
157 events. */
158
159/*---------------------------------------------------------------------------*/
160
161#include <stdio.h>
162#include <getopt.h>
163#include <limits.h>
164#include <errno.h>
64d538ce
ILT
165#include <ctype.h>
166#include "ansidecl.h"
8bae0a0c 167#include "opcode/mips.h"
8ad57737 168
64d538ce
ILT
169/* FIXME: ansidecl.h defines AND. */
170#undef AND
8bae0a0c 171
64d538ce
ILT
172#ifndef ULONG_MAX
173#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
174#endif
8bae0a0c 175
64d538ce 176static unsigned long my_strtoul ();
8ad57737 177
8bae0a0c 178#if 0
8ad57737
JSC
179#ifndef TRUE
180#define TRUE (1 == 1)
181#define FALSE (1 == 0)
182#endif
8bae0a0c 183#endif
8ad57737
JSC
184
185/*---------------------------------------------------------------------------*/
186
187/* Holding the instruction table this way makes it easier to check the
188 instruction values defined, and to add instructions to the
189 system. However, it makes the process of constructing the simulator
190 a bit more complicated: */
191
192/* The "bitmap" is encoded as follows (NOTE: Only lower-case
193 alphabetic characters should be used, since the letter ordinal is
194 used as a bit position): */
195
196typedef struct operand_encoding {
197 char id; /* character identifier */
198 int fpos; /* first bit position */
199 int flen; /* field length in bits */
200 char * const type;
201 char * const name;
202 unsigned int flags;
203} operand_encoding;
204
205/* Values for the "flags" field: */
206#define OP_NONE (0 << 0) /* To keep the source tidy */
207#define OP_GPR (1 << 0) /* Get operand from integer register bank */
8bae0a0c
JSC
208#define OP_SIGNX (1 << 1) /* Sign-extend the operand */
209#define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
210#define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
8ad57737
JSC
211
212struct operand_encoding opfields[] = {
8bae0a0c
JSC
213 {'0',-1,-1,"", "", (OP_NONE)}, /* special case for explicit zero */
214 {'1',-1,-1,"", "", (OP_NONE)}, /* special case for explicit one */
215 {'?',-1,-1,"", "", (OP_NONE)}, /* undefined (do not care at this level) */
8ad57737 216 /* The rest are the explicit operand fields: */
8bae0a0c
JSC
217 {'a', 6, 5,"int", "op1", (OP_NONE)}, /* shift amount (or hint) */
218 {'b',21, 5,"int", "fr", (OP_NONE)}, /* fr register */
219 {'c',16, 1,"int", "boolean", (OP_NONE)}, /* TRUE or FALSE boolean */
220 {'d',11, 5,"int", "destreg", (OP_NONE)}, /* integer destination/rd register */
221 {'e', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-3bits must be zero) */
222 {'f',17, 1,"int", "likely", (OP_NONE)}, /* set if branch LIKELY */
223 {'g',16, 5,"t_reg", "op2", (OP_GPR)}, /* integer source rt register */
224 {'h', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-1bit must be zero) */
225 {'i', 0,16,"t_reg", "op2", (OP_SIGNX)}, /* signed immediate (op2) */
226 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
227 {'k',16, 5,"int", "ft", (OP_NONE)},
228 {'l', 0,16,"t_reg", "offset", (OP_SIGNX | OP_SHIFT2)}, /* signed offset shifted left 2 to make 18bit signed offset */
229 {'m',21, 3,"int", "format", (OP_NONE)}, /* FP format field */
230 {'n',16, 5,"int", "hint", (OP_NONE)}, /* hint */
231 {'o',21, 5,"t_reg", "op1", (OP_GPR | OP_BITS5)}, /* integer source/rs register (but never treated as 32bit word) */
232 {'p', 8, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
233 {'q',18, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
234 {'r', 6, 5,"int", "destreg", (OP_NONE)}, /* FP fd register */
235 {'s',21, 5,"t_reg", "op1", (OP_GPR)}, /* integer source/rs register */
236 {'t',16, 5,"int", "destreg", (OP_NONE)}, /* integer target rt (destination) register */
237 {'u', 0, 4,"int", "cmpflags", (OP_NONE)}, /* FP comparison control flags */
238 {'v',11, 5,"int", "fs", (OP_NONE)}, /* FP fs register (or PREFX hint) */
239 {'w', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-2bits must be zero) */
240 {'x',23, 1,"int", "to", (OP_NONE)}, /* TRUE if move To; FALSE if move From */
241 {'y', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset */
242 {'z', 0,16,"ut_reg","op2", (OP_NONE)}, /* unsigned immediate (zero extended) */
8ad57737
JSC
243};
244
245/* Main instruction encoding types: */
246typedef enum {
247 NORMAL,
248 SPECIAL,
249 REGIMM,
250 COP1,
251 COP1X,
8bae0a0c 252 COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
831f59a2
ILT
253
254 /* mips16 encoding types. */
255 I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64
8ad57737
JSC
256} inst_type;
257
258/* Main instruction families: */
259typedef enum {
260 ADD, /* res = operand1 + operand2 */
261 SUB, /* res = operand1 - operand2 */
262 MUL, /* res = operand1 * operand2 */
263 DIV, /* res = operand1 / operand2 */
264 AND, /* res = operand1 & operand2 */
265 OR, /* res = operand1 | operand2 */
266 XOR, /* res = operand1 ^ operand2 */
267 MOVE, /* res = operand1 */
268 BRANCH, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
269 JUMP, /* execute delay slot instruction before jump */
270 LOAD, /* load from memory */
271 STORE, /* store to memory */
272 PREFETCH, /* prefetch data into cache */
273 SET, /* set register on result of condition code */
274 SHIFT, /* perform a logical or arithmetic shift */
275 TRAP, /* system exception generation */
276 BREAK, /* system breakpoint exception generation */
277 SYSCALL, /* system exception generation */
278 SYNC, /* system cache control */
279 DECODE, /* co-processor instruction */
280 CACHE, /* co-processor 0 CACHE instruction */
281 MADD16, /* VR4100 specific multiply-add extensions */
282 FPMOVE,
8bae0a0c 283 FPMOVEC,
8ad57737
JSC
284 FPFLOOR,
285 FPCEIL,
286 FPTRUNC,
287 FPROUND,
288 FPNEG,
289 FPABS,
290 FPDIV,
291 FPMUL,
292 FPSUB,
293 FPADD,
8ad57737 294 FPPREFX,
8ad57737
JSC
295 FPRECIP,
296 FPSQRT,
297 FPCONVERT,
298 FPCOMPARE,
299 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
300} opcode_type;
301
302/* Flags field: */
303#define NONE (0 << 0) /* Zero value (used to keep source tidy) */
304#define SIM_SH_SIZE (0)
8bae0a0c
JSC
305#define SIM_MASK_SIZE (0x7)
306#define BYTE (0) /* 8bit */
307#define HALFWORD (1) /* 16bit */
308#define WORD (2) /* 32bit */
309#define DOUBLEWORD (3) /* 64bit */
310#define SINGLE (4) /* single precision FP */
311#define DOUBLE (5) /* double precision FP */
8ad57737
JSC
312
313/* Shorthand to get the size field from the flags value: */
314#define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
831f59a2 315#define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
8ad57737
JSC
316
317/* The rest are single bit flags: */
8ad57737
JSC
318#define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
319#define EQ (1 << 4)
320#define GT (1 << 5)
321#define LT (1 << 6)
322#define NOT (1 << 7)
323#define LIKELY (1 << 8)
324#define SIGNEXTEND (1 << 9)
325#define OVERFLOW (1 << 10)
326#define LINK (1 << 11)
327#define ATOMIC (1 << 12)
328#define SHIFT16 (1 << 13)
329#define REG (1 << 14)
330#define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
331#define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
332#define LOGICAL (1 << 17)
333#define ARITHMETIC (1 << 18)
334#define UNSIGNED (1 << 19)
335#define HI32 (1 << 20)
336#define HI (1 << 21) /* accesses or updates the HI register */
337#define LO (1 << 22) /* accesses or updates the LO register */
338#define WORD32 (1 << 23)
339#define FP (1 << 24) /* Floating Point operation */
340#define FIXED (1 << 25) /* fixed point arithmetic */
8bae0a0c
JSC
341#define COPROC (1 << 26)
342#define INTEGER (1 << 27)
343#define CONDITIONAL (1 << 28)
344#define RECIP (1 << 29)
345#define CONTROL (1 << 30)
8ad57737 346#define NOARG (1 << 31) /* Instruction has no (defined) operands */
8bae0a0c
JSC
347/* NOTE: We can overload the use of certain of these flags, since not
348 all options are applicable to all instruction types. This will free
349 up more space for new flags. */
8ad57737
JSC
350
351typedef struct instruction {
352 char *name; /* ASCII mnemonic name */
353 unsigned int isa; /* MIPS ISA number where instruction introduced */
354 char *bitmap; /* 32character string describing instruction operands */
355 inst_type mark; /* type of MIPS instruction encoding */
356 opcode_type type; /* main instruction family */
357 unsigned int flags; /* flags describing instruction features */
358} instruction;
359/* The number of pipeline cycles taken by an instruction varies
360 between MIPS processors. This means that the information must be
361 encoded elsewhere, in a CPU specific structure. */
362
363/* NOTE: Undefined instructions cause "Reserved Instruction"
364 exceptions. i.e. if there is no bit-mapping defined then the
365 instruction is deemed to be undefined. */
366
367/* NOTE: The "isa" field is also used to encode flags for particular
368 chip architecture extensions. e.g. the NEC VR4100 specific
369 instructions. Normally chip extensions are added via the COP0
370 space. However, the VR4100 (and possibly other devices) also use
371 the normal instruction space. */
372#define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
373/* The other bits are allocated downwards, to avoid renumbering if we
374 have to extend the bits allocated to the pure ISA number. */
375#define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
376
377/* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
378 COP0 space. This means that an external decoder should be added
379 when constructing a full VR4100 simulator. However some arithmetic
380 instructions are encoded in the normal instruction space. */
381
382struct instruction MIPS_DECODE[] = {
383 /* The instructions are alphabetical, and not in instruction bit-order: */
a9f7253f 384 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1, FPABS, (FP)},
8ad57737 385 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */
8bae0a0c 386 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)},
8ad57737
JSC
387 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)},
388 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL,ADD, (WORD | WORD32)}, /* rd = rs + rt */
389 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32)},
390 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL,AND, (NONE)}, /* rd = rs AND rt */
391 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND, (NONE)},
8bae0a0c 392 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S, BRANCH, (FP)},
8ad57737
JSC
393 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ)},
394 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ | LIKELY)},
395 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH, (GT | EQ)},
396 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
397 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
398 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LIKELY)},
399 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT)},
400 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT | LIKELY)},
401 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ)},
402 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ | LIKELY)},
403 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH, (LT)},
404 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH, (LT | LINK)},
405 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM, BRANCH, (LT | LINK | LIKELY)},
406 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM, BRANCH, (LT | LIKELY)},
407 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ)},
408 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ | LIKELY)},
409 {"BREAK", 1,"000000????????????????????001101",SPECIAL,BREAK, (NOARG)},
410 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1, FPCEIL, (FP | FIXED | DOUBLEWORD)},
411 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1, FPCEIL, (FP | FIXED | WORD)},
412 {"COP0", 1,"010000??????????????????????????",NORMAL, DECODE, (NOARG)},
413 {"COP2", 1,"010010??????????????????????????",NORMAL, DECODE, (NOARG)},
414 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1, FPCONVERT,(FP | DOUBLE)},
415 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1, FPCONVERT,(FP | FIXED | DOUBLEWORD)},
416 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1, FPCONVERT,(FP | SINGLE)},
417 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1, FPCONVERT,(FP | FIXED | WORD)},
418 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1, FPCOMPARE,(FP)},
8bae0a0c 419 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD | CONTROL)},
8ad57737
JSC
420 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL,ADD, (DOUBLEWORD | OVERFLOW)},
421 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | OVERFLOW)},
422 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL,ADD, (DOUBLEWORD | UNSIGNED)},
423 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | UNSIGNED)},
424 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL,DIV, (DOUBLEWORD | HI | LO)},
425 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL,DIV, (DOUBLEWORD | UNSIGNED | HI | LO)},
426 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO)},
427 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1, FPDIV, (FP | WORD | HI | LO)},
428 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
429 {"DMADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101001",SPECIAL,MADD16, (DOUBLEWORD | HI | LO)},
430 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL,MUL, (DOUBLEWORD | HI | LO)},
431 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL,MUL, (DOUBLEWORD | UNSIGNED | HI | LO)},
8bae0a0c 432 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | DOUBLEWORD)},
8ad57737 433 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)},
831f59a2 434 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | REG)},
8ad57737
JSC
435 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */
436 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
831f59a2 437 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | REG)},
8ad57737
JSC
438 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */
439 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
831f59a2 440 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | REG)},
8ad57737
JSC
441 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)},
442 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)},
443 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)},
444 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1, FPFLOOR, (FP | FIXED | DOUBLEWORD)},
445 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1, FPFLOOR, (FP | FIXED | WORD)},
446 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */
447 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */
448 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)},
831f59a2 449 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK | NOT)},
8ad57737
JSC
450 {"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */
451 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
452 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */
453 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD)},
454 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
455 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
456 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | LEFT)}, /* NOTE: See "LB" comment */
457 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | RIGHT)}, /* NOTE: See "LB" comment */
8bae0a0c 458 {"LDXC1", 4,"010011sssssggggg00000rrrrr000001",COP1X, LOAD, (FP | DOUBLEWORD | COPROC | REG)},
8ad57737
JSC
459 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD | SIGNEXTEND)},
460 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD)},
461 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | ATOMIC | SIGNEXTEND)},
462 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | ATOMIC)},
463 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE, (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
464 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | SIGNEXTEND)},
465 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
466 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
467 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | LEFT)},
468 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | RIGHT)},
469 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD)},
8bae0a0c 470 {"LWXC1", 4,"010011sssssggggg00000rrrrr000000",COP1X, LOAD, (FP | WORD | COPROC | REG)},
8ad57737
JSC
471 {"MADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101000",SPECIAL,MADD16, (WORD | HI | LO)},
472 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X, FPADD, (FP | MULTIPLY | DOUBLE)},
473 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X, FPADD, (FP | MULTIPLY | SINGLE)},
831f59a2
ILT
474 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI | LEFT)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
475 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO | LEFT)},
476 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI | RIGHT)},
477 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO | RIGHT)},
8ad57737
JSC
478 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1, FPMOVE, (FP)},
479 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL,MOVE, (NOT | EQ)},
8bae0a0c
JSC
480 {"MOVN", 4,"01000110mmmgggggvvvvvrrrrr010011",COP1, FPMOVE, (FP | NOT | EQ)},
481 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE, (FP | CONDITIONAL | INTEGER)},
482 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1, FPMOVE, (FP | CONDITIONAL)},
8ad57737 483 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL,MOVE, (EQ)},
8bae0a0c 484 {"MOVZ", 4,"01000110mmmgggggvvvvvrrrrr010010",COP1, FPMOVE, (FP | EQ)},
8ad57737
JSC
485 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X, FPSUB, (FP | MULTIPLY | DOUBLE)},
486 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)},
487 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)},
488 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL,MUL, (WORD | WORD32 | HI | LO)},
458e1f58 489 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL,MUL, (WORD | WORD32 | UNSIGNED | HI | LO)},
8bae0a0c
JSC
490 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)},
491 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)},
8ad57737
JSC
492 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)},
493 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X, FPADD, (FP | NOT | MULTIPLY | SINGLE)},
494 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X, FPSUB, (FP | NOT | MULTIPLY | DOUBLE)},
495 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X, FPSUB, (FP | NOT | MULTIPLY | SINGLE)},
496 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL,OR, (NOT)},
497 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL,OR, (NONE)},
498 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR, (NONE)},
499 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
8bae0a0c 500 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X, FPPREFX, (FP)},
8ad57737
JSC
501 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1, FPRECIP, (FP)},
502 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1, FPROUND, (FP | FIXED | DOUBLEWORD)},
503 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1, FPROUND, (FP | FIXED | WORD)},
8bae0a0c 504 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1, FPSQRT, (FP | RECIP)},
8ad57737
JSC
505 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (BYTE)},
506 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | ATOMIC)},
507 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | ATOMIC)},
508 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD)},
509 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
510 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
511 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | LEFT)},
512 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | RIGHT)},
8bae0a0c 513 {"SDXC1", 4,"010011sssssgggggvvvvv00000001001",COP1X, STORE, (FP | DOUBLEWORD | COPROC | REG)},
8ad57737
JSC
514 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE, (HALFWORD)},
515 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
516 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
517 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL,SET, (LT)},
518 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT)},
519 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL,SET, (LT | UNSIGNED)},
520 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT | UNSIGNED)},
521 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1, FPSQRT, (FP)},
8bae0a0c
JSC
522 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
523 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
524 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
525 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
8ad57737
JSC
526 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL,SUB, (WORD | WORD32 | OVERFLOW)},
527 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1, FPSUB, (FP)},
528 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL,SUB, (WORD | WORD32)},
529 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD)},
530 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
531 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
532 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | LEFT)},
533 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | RIGHT)},
8bae0a0c 534 {"SWXC1", 4,"010011sssssgggggvvvvv00000001000",COP1X, STORE, (FP | WORD | COPROC | REG)},
8ad57737
JSC
535 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL,SYNC, (NONE)}, /* z = 5bit stype field */
536 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL, (NOARG)},
537 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL,TRAP, (EQ)},
538 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP, (EQ)},
539 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL,TRAP, (GT | EQ)},
540 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ)},
541 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ | UNSIGNED)},
542 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL,TRAP, (GT | EQ | UNSIGNED)},
543 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL,TRAP, (LT)},
544 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT)},
545 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT | UNSIGNED)},
546 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL,TRAP, (LT | UNSIGNED)},
547 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL,TRAP, (NOT | EQ)},
548 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM, TRAP, (NOT | EQ)},
549 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1, FPTRUNC, (FP | FIXED | DOUBLEWORD)},
550 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1, FPTRUNC, (FP | FIXED | WORD)},
551 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL,XOR, (NONE)},
552 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR, (NONE)},
553 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE, (NONE)},
554 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD, (NONE)},
555};
556
831f59a2
ILT
557static const struct instruction MIPS16_DECODE[] = {
558{"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 },
559{"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 },
560{"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 },
561{"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 },
562{"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 },
563{"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 },
564{"AND", 1, "11101wwwyyy01100", RR, AND, NONE },
565{"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ },
566{"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ },
567{"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ },
568{"BREAK", 1, "01100??????00101", RR, BREAK, NOARG },
569{"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ },
570{"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ },
571{"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE },
572{"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE },
573{"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD },
574{"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD },
575{"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD },
576{"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD },
577{"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD },
578{"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD },
579{"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO },
580{"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO },
581{"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO },
582{"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO },
583{"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO },
584{"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO },
585{"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL },
586{"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG },
587{"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC },
588{"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG},
589{"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL },
590{"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG},
591{"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED},
592#if 0
593 /* FIXME: Should we handle these ourselves, or should we require an
594 emulation routine? */
595{"EXIT", 1, "1110111100001000", RR, BREAK, EXIT },
596{"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY },
597#endif
598{"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG },
599{"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG },
600{"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK },
601{"JR", 1, "11101xxx00000000", RR, JUMP, NONE },
602{"JRRA", 1, "1110100000100000r", RR, JUMP, NONE },
603{"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND },
604{"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE },
605{"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD },
606{"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD },
607{"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD },
608{"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND },
609{"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD },
610{"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE },
611{"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND },
612{"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND },
613{"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND },
614{"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD },
615{"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT },
616{"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT },
617{"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE },
618{"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE },
619{"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO},
620{"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO },
621{"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD },
622{"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT },
623{"OR", 1, "11101wwwyyy01101", RR, OR, NONE },
624{"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE },
625{"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD },
626{"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD },
627{"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD },
628{"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD },
629{"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL },
630{"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG},
631{"SLT", 1, "11101xxxyyy00010T", RR, SET, LT },
632{"SLTI", 1, "01010xxx88888888T", RI, SET, LT },
633{"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED },
634{"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED },
635{"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC },
636{"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG },
637{"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL },
638{"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG },
639{"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 },
640{"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD },
641{"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD },
642{"SWRASP", 1, "01100010VVVVVVVVQs", RI, STORE, WORD },
643{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
644};
645
646static int bitmap_val PARAMS ((const char *, int, int));
647static void build_mips16_operands PARAMS ((const char *));
648static void build_instruction
649 PARAMS ((int, unsigned int, int, const struct instruction *));
650
8ad57737
JSC
651/*---------------------------------------------------------------------------*/
652
653/* We use the letter ordinal as the bit-position in our flags field: */
654#define fieldval(l) (1 << ((l) - 'a'))
655
656unsigned int
657convert_bitmap(bitmap,onemask,zeromask,dontmask)
658 char *bitmap;
659 unsigned int *onemask, *zeromask, *dontmask;
660{
661 unsigned int flags = 0x00000000;
662 int loop; /* current bitmap position */
663 int lastsp = -1; /* last bitmap field starting position */
664 int lastoe = -1; /* last bitmap field encoding */
665
666 *onemask = 0x00000000;
667 *zeromask = 0x00000000;
668 *dontmask = 0x00000000;
669
670 if (strlen(bitmap) != 32) {
671 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
672 exit(3);
673 }
674
675 for (loop = 0; (loop < 32); loop++) {
676 int oefield ;
677 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
678 if (bitmap[31 - loop] == opfields[oefield].id)
679 break;
680 if (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))) {
681 if ((lastoe != -1) && (lastoe != oefield))
682 if ((loop - lastsp) != (opfields[lastoe].flen)) {
8bae0a0c 683 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);
8ad57737
JSC
684 exit(4);
685 }
686
687 switch (bitmap[31 - loop]) {
688 case '0' : /* fixed value */
689 *zeromask |= (1 << loop);
690 lastsp = loop;
691 lastoe = -1;
692 break;
693
694 case '1' : /* fixed value */
695 *onemask |= (1 << loop);
696 lastsp = loop;
697 lastoe = -1;
698 break;
699
700 case '?' : /* fixed value */
701 *dontmask |= (1 << loop);
702 lastsp = loop;
703 lastoe = -1;
704 break;
705
706 default : /* check character encoding */
707 {
708 if (opfields[oefield].fpos != -1) {
709 /* If flag not set, then check starting position: */
710 if (!(flags & fieldval(bitmap[31 - loop]))) {
711 if (loop != opfields[oefield].fpos) {
712 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);
713 exit(4);
714 }
715 flags |= fieldval(bitmap[31 - loop]);
716 lastsp = loop;
717 lastoe = oefield;
718 }
719 }
720 *dontmask |= (1 << loop);
721 }
722 break;
723 }
724 } else {
725 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);
726 exit(4);
727 }
728 }
729
730 /* NOTE: Since we check for the position and size of fields when
731 parsing the "bitmap" above, we do *NOT* need to check that invalid
732 field combinations have been used. */
733
734 return(flags);
735}
736
831f59a2
ILT
737/* Get the value of a 16 bit bitstring for a given shift count and
738 number of bits. */
739
740static int
741bitmap_val (bitmap, shift, bits)
742 const char *bitmap;
743 int shift;
744 int bits;
745{
746 const char *s;
747 int ret;
748
749 ret = 0;
750 s = bitmap + 16 - shift - bits;
751 for (; bits > 0; --bits)
752 {
753 ret <<= 1;
754 if (*s == '0')
755 ;
756 else if (*s == '1')
757 ret |= 1;
758 else
759 abort ();
760 ++s;
761 }
762
763 return ret;
764}
765
8ad57737
JSC
766/*---------------------------------------------------------------------------*/
767
768static void
769build_operands(flags)
770 unsigned int flags;
771{
772 int loop;
773 for (loop = 0; (loop < (sizeof(opfields) / sizeof(operand_encoding))); loop++)
774 if ((opfields[loop].fpos != -1) && (flags & fieldval(opfields[loop].id))) {
775 printf(" %s %s = ",opfields[loop].type,opfields[loop].name);
776
777 if (opfields[loop].flags & OP_SIGNX)
778 printf("SIGNEXTEND((%s)",opfields[loop].type);
779
8bae0a0c
JSC
780 if (opfields[loop].flags & OP_GPR)
781 printf("GPR[");
8ad57737
JSC
782
783 if (opfields[loop].flags & OP_SHIFT2)
784 printf("(");
785
786 printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
787
788 if (opfields[loop].flags & OP_SHIFT2)
789 printf(" << 2)");
790
8bae0a0c 791 if (opfields[loop].flags & OP_GPR)
8ad57737
JSC
792 printf("]");
793
794 if (opfields[loop].flags & OP_BITS5)
795 printf("&0x1F");
796
797 if (opfields[loop].flags & OP_SIGNX)
798 printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
799
800 printf(";\n");
801 }
802
803 return;
804}
805
831f59a2
ILT
806/* The mips16 operand table. */
807
808struct mips16_op
809{
810 /* The character which appears in the bitmap string. */
811 int type;
812 /* The type of the variable in the simulator. */
813 const char *vartype;
814 /* The name of the variable in the simulator. */
815 const char *name;
816 /* The number of bits. */
817 int nbits;
818 /* The number of bits when extended (zero if can not be extended). */
819 int extbits;
820 /* The amount by which the short form is shifted when it is used;
821 for example, the sw instruction has a shift count of 2. */
822 int shift;
823 /* Flags. */
824 int flags;
825};
826
827/* Flags which appears in the mips16 operand table. */
828
829/* Whether this is a mips16 register index. */
830#define MIPS16_REG16 (0x1)
831/* Whether this is a register value. */
832#define MIPS16_REGVAL (0x2)
833/* Whether this is a swapped mips32 register index (MOV32R) */
834#define MIPS16_REG32_SWAPPED (0x4)
835/* Whether this index is also the destination register. */
836#define MIPS16_DESTREG (0x8)
837/* Whether the short form is unsigned. */
838#define MIPS16_UNSP (0x10)
839/* Whether the extended form is unsigned. */
840#define MIPS16_EXTU (0x20)
841/* Implicit stack pointer. */
842#define MIPS16_SP (0x40)
843/* Implicit program counter. */
844#define MIPS16_PC (0x80)
845/* Implicit $0. */
846#define MIPS16_ZERO (0x100)
847/* Implicit $24. */
848#define MIPS16_TREG (0x200)
849/* Implicit $31. */
850#define MIPS16_RA (0x400)
851/* Jump address. */
852#define MIPS16_JUMP_ADDR (0x800)
853/* Branch offset. */
854#define MIPS16_BRANCH (0x1000)
855
856/* The mips16 operand table. */
857
858static const struct mips16_op mips16_op_table[] =
859{
860 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16 },
861 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
862 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG},
863 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
864 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG },
865 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL },
866 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED },
867 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR },
868 { 'e', "int", "ext", 11, 0, 0, 0 },
869 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
870 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
871 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
872 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
873 { '4', "int", "op2", 4, 15, 0, 0 },
874 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP },
875 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP },
876 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP },
877 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP },
878 { 'j', "int", "op2", 5, 16, 0, 0 },
879 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP },
880 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP },
881 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP },
882 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP | MIPS16_EXTU },
883 { 'k', "int", "op2", 8, 16, 0, 0 },
884 { 'K', "int", "op2", 8, 16, 3, 0 },
885 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH },
886 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH },
887 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP },
888 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP },
889 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP },
890
891 /* The remaining operands are special operands which encode implied
892 arguments. These only appear at the end of a bitmap string, and
893 do not represent actual bits. */
894 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP | MIPS16_REGVAL },
895 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP|MIPS16_REGVAL|MIPS16_DESTREG },
896 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC },
897 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO },
898 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO },
899 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG | MIPS16_REGVAL },
900 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG },
901 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
902 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA },
903 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
904
905 { '\0', NULL, NULL, 0, 0, 0, 0 }
906};
907
908/* Build mips16 operands. */
909
910static void
911build_mips16_operands (bitmap)
912 const char *bitmap;
913{
914 const char *s;
915 int start = -1;
916 const struct mips16_op *op = NULL;
917 const struct mips16_op *ops[3];
918 int opindex = 0;
919 int i;
920
921 for (s = bitmap; *s != '\0'; s++)
922 {
923 if (op != NULL)
924 {
925 if (op->type == *s)
926 continue;
927
928 /* Make sure we saw the right number of bits for that
929 operand. */
930 if (op->nbits != 0 && (s - bitmap) - op->nbits != start)
931 abort ();
932 op = NULL;
933 }
934
935 if (*s == '0' || *s == '1' || *s == '?')
936 continue;
937
938 start = s - bitmap;
939
940 for (op = mips16_op_table; op->type != *s; ++op)
941 if (op->type == '\0')
942 abort ();
943
944 printf (" %s %s = ", op->vartype, op->name);
945 if (op->nbits != 0)
946 printf ("(instruction >> %d) & 0x%x",
947 16 - (s - bitmap) - op->nbits,
948 (1 << op->nbits) - 1);
949 else
950 {
951 if ((op->flags & MIPS16_SP) != 0)
952 printf ("29");
953 else if ((op->flags & MIPS16_PC) != 0)
954 {
955 int j;
956
aaff8437 957 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : IPC) & ~ (uword64) 1)");
831f59a2
ILT
958 for (j = 0; j < opindex; j++)
959 if (ops[j]->shift != 0)
aaff8437 960 printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
831f59a2
ILT
961 }
962 else if ((op->flags & MIPS16_ZERO) != 0)
963 printf ("0");
964 else if ((op->flags & MIPS16_TREG) != 0)
965 printf ("24");
966 else if ((op->flags & MIPS16_RA) != 0)
967 printf ("31");
968 else
969 abort ();
970 }
971 printf (";\n");
972
973 if ((op->flags & MIPS16_DESTREG) != 0)
974 printf (" int destreg;\n");
975
976 if (opindex > 2)
977 abort ();
978 ops[opindex] = op;
979 ++opindex;
980 }
981
982 if (op != NULL)
983 {
984 /* Make sure we saw the right number of bits for that
985 operand. */
986 if (op->nbits != 0 && 16 - op->nbits != start)
987 abort ();
988 }
989
990 for (i = 0; i < opindex; i++)
991 {
992 op = ops[i];
993 if ((op->flags & MIPS16_REG16) != 0)
994 {
995 printf (" if (%s < 2)\n", op->name);
996 printf (" %s += 16;\n", op->name);
997 }
998 if ((op->flags & MIPS16_REG32_SWAPPED) != 0)
999 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1000 op->name, op->name, op->name);
1001 if ((op->flags & MIPS16_DESTREG) != 0)
1002 printf (" destreg = %s;\n", op->name);
1003 if ((op->flags & MIPS16_REGVAL) != 0)
1004 printf (" %s = GPR[%s];\n", op->name, op->name);
1005
1006 if (op->extbits != 0)
1007 {
1008 printf (" if (have_extendval)\n");
1009 printf (" {\n");
1010 if (op->extbits == 16)
1011 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1012 op->name);
1013 else if (op->extbits == 15)
1014 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1015 op->name);
1016 else if (op->extbits == 6)
1017 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1018 op->name);
1019 else
1020 printf (" %s = (extendval >> 6) & 0x1f;\n",
1021 op->name);
1022 if ((op->flags & MIPS16_EXTU) == 0)
1023 {
1024 printf (" if (%s >= 0x%x)\n",
1025 op->name, 1 << (op->extbits - 1));
1026 printf (" %s -= 0x%x;\n",
1027 op->name, 1 << op->extbits);
1028 }
1029 printf (" have_extendval = 0;\n");
1030 printf (" }\n");
1031 printf (" else\n");
1032 printf (" {\n");
1033 if ((op->flags & MIPS16_UNSP) == 0)
1034 {
1035 printf (" if (%s >= 0x%x)\n",
1036 op->name, 1 << (op->nbits - 1));
1037 printf (" %s -= 0x%x;\n",
1038 op->name, 1 << op->nbits);
1039 }
1040 if (op->shift != 0)
1041 printf (" %s <<= %d;\n", op->name, op->shift);
1042 if (op->type == '<' || op->type == '>'
1043 || op->type == '[' || op->type == ']')
1044 {
1045 printf (" if (%s == 0)\n", op->name);
1046 printf (" %s = 8;\n", op->name);
1047 }
1048 printf (" }\n");
1049 }
1050
1051 if ((op->flags & MIPS16_BRANCH) != 0)
1052 printf (" %s *= 2;\n", op->name);
1053
1054 if ((op->flags & MIPS16_JUMP_ADDR) != 0)
1055 {
1056 printf (" {\n");
1057 printf (" uword64 paddr;\n");
1058 printf (" int uncached;\n");
1059 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1060 printf (" {\n");
1061 printf (" uword64 memval;\n");
1062 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1063 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1064 printf (" unsigned int byte;\n");
1065 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1066 printf (" memval = LoadMemory (uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1067 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1068 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1069 printf (" %s = (((%s & 0x1f) << 23)\n", op->name, op->name);
1070 printf (" | ((%s & 0x3e0) << 13)\n", op->name);
1071 printf (" | (memval << 2));\n");
1072 printf (" if ((instruction & 0x400) == 0)\n");
1073 printf (" %s |= 1;\n", op->name);
1074 printf (" PC += 2;\n");
1075 printf (" }\n");
1076 printf (" }\n");
1077 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op->name);
1078 }
1079 }
1080
1081 /* FIXME: Is this the way to detect an unused extend opcode? */
1082 printf (" if (have_extendval)\n");
1083 printf (" SignalException (ReservedInstruction, instruction);\n");
1084}
1085
e871dd18
JSC
1086/*---------------------------------------------------------------------------*/
1087
1088typedef enum {
1089 s_left,
1090 s_right
1091} e_endshift;
1092
1093static void
1094build_endian_shift(proc64,datalen,endbit,direction,shift)
1095 int proc64;
1096 int datalen;
1097 int endbit;
1098 e_endshift direction;
1099 int shift;
1100{
1101 if (proc64 && (datalen == 4)) {
1102 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit,endbit);
1103 printf(" memval %s= %d;\n",direction == s_left ? "<<" : ">>",shift);
1104 printf(" }\n");
1105 }
1106
1107 return;
1108}
1109
8ad57737
JSC
1110/*---------------------------------------------------------------------------*/
1111/* doisa = number of MIPS ISA simulator table is being constructed for.
1112 * proc64 = TRUE if constructing 64bit processor world.
1113 * dofp = boolean, TRUE if FP instructions are to be included.
1114 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1115 */
1116
1117void
1118process_instructions(doarch,features)
1119 unsigned int doarch;
1120 unsigned int features;
1121{
1122 int doisa = (doarch & MASK_ISA);
1123 int limit = (sizeof(MIPS_DECODE) / sizeof(instruction));
1124 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
8ad57737
JSC
1125 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1126 int dofp = (features & FEATURE_HASFPU);
1127 int fpsingle = (features & FEATURE_FPSINGLE);
8bae0a0c 1128 int maxisa;
8ad57737
JSC
1129 int loop;
1130
1131 if (limit < 1) {
1132 fprintf(stderr,"process_instructions: invalid structure length\n");
1133 exit(1);
1134 }
1135
1136 if (proc64 && (gprlen != 64)) {
1137 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1138 exit(3);
1139 }
1140
8ad57737
JSC
1141 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1142
8bae0a0c
JSC
1143 maxisa = 0;
1144 for (loop = 0; (loop < limit); loop++)
1145 if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa)
1146 maxisa = (MIPS_DECODE[loop].isa & MASK_ISA);
1147
1148 if (doisa == 0)
1149 doisa = maxisa;
1150
8ad57737 1151 printf("#if defined(SIM_MANIFESTS)\n");
8bae0a0c 1152 printf("#define MIPSISA (%d)\n",doisa);
8ad57737
JSC
1153 if (proc64)
1154 printf("#define PROCESSOR_64BIT (1 == 1)\n");
c98ec95d
JSC
1155 else
1156 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1157#if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1158 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1159#else
8ad57737 1160 printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
c98ec95d 1161#endif
8bae0a0c 1162 /* The FP registers are the same width as the CPU registers: */
8ad57737 1163 printf("#define GPRLEN (%d)\n",gprlen);
8ad57737
JSC
1164 printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
1165 printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
8bae0a0c 1166 printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
8ad57737
JSC
1167 if (dofp)
1168 printf("#define HASFPU (1 == 1)\n");
1169 if (features & FEATURE_FAST)
1170 printf("#define FASTSIM (1 == 1)\n");
1171 if (features & FEATURE_WARN_STALL)
1172 printf("#define WARN_STALL (1 == 1)\n");
1173 if (features & FEATURE_WARN_LOHI)
1174 printf("#define WARN_LOHI (1 == 1)\n");
1175 if (features & FEATURE_WARN_ZERO)
1176 printf("#define WARN_ZERO (1 == 1)\n");
1177 if (features & FEATURE_WARN_MEM)
1178 printf("#define WARN_MEM (1 == 1)\n");
1179 if (features & FEATURE_WARN_R31)
1180 printf("#define WARN_R31 (1 == 1)\n");
1181 if (features & FEATURE_WARN_RESULT)
1182 printf("#define WARN_RESULT (1 == 1)\n");
1183
1184 printf("#else /* simulator engine */\n");
1185
1186 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1187 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
1188 if (dofp)
1189 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
1190 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1191
1192 if (proc64) {
1193 printf("#if !defined(PROCESSOR_64BIT)\n");
1194 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1195 printf("#endif\n");
1196 }
1197
1198 printf("/* Actual instruction decoding block */\n");
831f59a2 1199 printf("if ((vaddr & 1) == 0){\n");
8bae0a0c
JSC
1200 {
1201 int limit;
1202 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
1203 limit = (OP_MASK_OP + 1);
1204 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1205 limit += (OP_MASK_SPEC + 1);
1206 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
1207 limit += (OP_MASK_RT + 1);
1208 printf("else if (num == 0x11) {\n");
1209 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
1210 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
1211 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
1212 printf(" else\n");
1213 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1214 limit += (OP_MASK_SPEC + 1);
1215 printf(" else\n");
1216 /* To keep this code quick, we just clear out the "to" bit
1217 here. The proper (though slower) code would be to have another
1218 conditional, checking whether this instruction is a branch or
1219 not, before limiting the range to the bottom two bits of the
1220 move operation. */
1221 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
1222 limit += (OP_MASK_COP1SPEC + 1);
1223 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1224 limit += (OP_MASK_SPEC + 1);
1225 printf("/* Total possible switch entries: %d */\n",limit) ;
1226 }
8ad57737
JSC
1227 printf("switch (num)\n") ;
1228 printf("{\n");
1229
a9f7253f 1230 for (loop = 0; (loop < limit); loop++) {
8ad57737
JSC
1231 /* First check that the ISA number we are constructing for is
1232 valid, before checking if the instruction matches any of the
1233 architecture specific flags. NOTE: We allow a selected ISA of
1234 zero to be used to match all standard instructions. */
8bae0a0c 1235 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))) {
8ad57737
JSC
1236 unsigned int onemask;
1237 unsigned int zeromask;
1238 unsigned int dontmask;
1239 unsigned int mask;
1240 unsigned int number;
1241 unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
8ad57737 1242
c98ec95d 1243 if (!(MIPS_DECODE[loop].flags & COPROC) && ((GETDATASIZE() == DOUBLEWORD) && !proc64)) {
8ad57737
JSC
1244 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
1245 exit(4);
1246 }
1247
1248#if defined(DEBUG)
1249 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
1250 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
1251 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
1252#endif
1253
1254 switch (MIPS_DECODE[loop].mark) {
1255 case NORMAL :
1256 mask = (OP_MASK_OP << OP_SH_OP) ;
1257 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
1258 break ;
1259
1260 case SPECIAL :
1261 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1262 number = ((OP_MASK_OP + 1) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1263 break ;
1264
1265 case REGIMM :
1266 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_RT << OP_SH_RT)) ;
1267 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_RT) & OP_MASK_RT)) ;
1268 break ;
1269
1270 case COP1 :
1271 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1272 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1273 break ;
1274
8bae0a0c
JSC
1275 case COP1S :
1276 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_COP1SPEC << OP_SH_COP1SPEC)) ;
1277 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_COP1SPEC) & OP_MASK_COP1SPEC)) ;
1278 break;
1279
8ad57737
JSC
1280 case COP1X :
1281 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
8bae0a0c 1282 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)) ;
8ad57737
JSC
1283 break ;
1284
1285 default :
1286 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
1287 exit(5) ;
1288 }
1289
1290 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
1291
1292#if defined(DEBUG)
1293 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
1294 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
1295#endif
1296
1297 /* Check if there are any other explicit bits in the instruction: */
1298 if ((~mask & (onemask | zeromask)) != 0x00000000) {
1299 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
1300 printf(" {\n") ;
1301 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1302 printf(" }\n") ;
1303 printf(" else\n") ;
1304 }
1305
1306 if ((flags == 0) && !(MIPS_DECODE[loop].flags & NOARG)) {
1307 fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE[loop].name) ;
1308 exit(5) ;
1309 }
1310
1311 printf(" {\n") ;
1312
1313 /* Get hold of the operands */
1314 /* NOTE: If we wanted to make the simulator code smaller, we
1315 * could pull these into a common sequence before we perform
1316 * the instruction decoding. However, this would affect the
1317 * performance since unnecessary field extraction would be
1318 * occurring for certain instructions.
1319 *
1320 * Also we do not perform checking for multiple definitions of a
1321 * particular operand here, since they are caught by the
1322 * compilation of the produced code.
1323 */
1324 build_operands(flags);
1325
1326 /* Finish constructing the jump address if required: */
1327 if (flags & fieldval('j'))
1328 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1329
1330 /* Now perform required operand checks: */
1331
1332/* The following code has been removed, since it seems perfectly
1333 reasonable to have a non-aligned offset that is added to another
1334 non-aligned base to create an aligned address. Some more
1335 information on exactly what the MIPS IV specification requires is
1336 needed before deciding on the best strategy. Experimentation with a
1337 VR4300 suggests that we do not need to raise the warning. */
1338#if 0
1339 /* For MIPS IV (and onwards), certain instruction operand values
1340 will give undefined results. For the simulator we could
1341 generate explicit exceptions (i.e. ReservedInstruction) to
1342 make it easier to spot invalid use. However, for the moment we
1343 just raise a warning. NOTE: This is a different check to the
1344 later decoding, which checks for the final address being
1345 valid. */
8bae0a0c 1346 if ((flags & (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa >= 4)) {
8ad57737
JSC
1347 printf(" if (instruction & 0x%1X)\n",((flags & fieldval('e')) ? 0x7 : ((flags & fieldval('w')) ? 0x3 : 0x1)));
1348 printf(" {\n");
1349 /* NOTE: If we change this to a SignalException(), we must
1350 ensure that the following opcode processing is not
1351 executed. i.e. the code falls straight out to the simulator
1352 control loop. */
f24b7b69 1353 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
8ad57737
JSC
1354 printf(" }\n");
1355 }
1356#endif
1357
1358 /* The extended condition codes only appeared in ISA IV */
8bae0a0c 1359 if ((flags & fieldval('p')) && (doisa < 4)) {
8ad57737
JSC
1360 printf(" if (condition_code != 0)\n");
1361 printf(" {\n");
1362 printf(" SignalException(ReservedInstruction,instruction);\n");
1363 printf(" }\n");
1364 printf(" else\n");
1365 }
1366
1367 if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
1368 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1369 exit(1);
1370 }
1371
8bae0a0c
JSC
1372#if 1
1373 /* The R4000 book differs slightly from the MIPS IV ISA
1374 manual. An example is the sign-extension of a 64-bit processor
1375 SUBU operation, and what is meant by an Undefined Result. This
1376 is now provided purely as a warning. After examining a HW
1377 implementation, this is now purely a warning... and the actual
1378 operation is performed, with possibly undefined results. */
1379 if (((MIPS_DECODE[loop].flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
1380 /* The compiler should optimise out an OR with zero */
1381 printf(" if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
1382 printf(" UndefinedResult();\n") ;
1383 }
1384#else
8ad57737
JSC
1385 /* Check that the source is a 32bit value */
1386 if ((MIPS_DECODE[loop].flags & WORD32) && proc64) {
8bae0a0c 1387 /* The compiler should optimise out an OR with zero */
8ad57737
JSC
1388 printf(" if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
1389 printf(" UndefinedResult();\n") ;
1390 printf(" else\n") ;
1391 }
8bae0a0c 1392#endif
8ad57737
JSC
1393
1394 printf(" {\n") ;
1395
831f59a2 1396 build_instruction (doisa, features, 0, &MIPS_DECODE[loop]);
8ad57737 1397
831f59a2
ILT
1398 printf(" }\n") ;
1399 printf(" }\n") ;
1400 printf(" break ;\n") ;
1401 }
1402 }
8ad57737 1403
831f59a2
ILT
1404 printf("default : /* Unrecognised instruction */\n") ;
1405 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1406 printf(" break ;\n") ;
1407 printf("}\n}\n") ;
8ad57737 1408
831f59a2
ILT
1409 /* Handle mips16 instructions. The switch table looks like this:
1410 0 - 31: I, RI, and RRI instructions by major.
1411 32 - 35: ISHIFT instructions by function + 32
1412 36 - 37: RRI_A instructions by function + 36
1413 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
1414 46 - 49: RRR instructions by function + 46
1415 50 - 81: RR instructions by minor + 50 (except for minor == 0)
1416 82 - 89: I64 and RI64 instructions by funct + 82
1417 90 - 97: jalr (RR minor 0) by y + 90
1418 */
1419 printf ("else {\n");
1420 printf ("static int extendval;\n");
1421 printf ("static int have_extendval;\n");
1422 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
1423 MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
1424 printf ("switch (num)\n{\n");
1425 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
1426 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
1427 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
1428 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
1429 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
1430 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
1431 printf (" break;\n");
1432 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
1433 printf ("default: break;\n}\n");
1434 printf ("switch (num)\n{\n");
1435
1436 for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++)
1437 {
1438 const char *bitmap;
1439 int num;
1440
279cca90
ILT
1441 if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD)
1442 continue;
1443
831f59a2
ILT
1444 bitmap = MIPS16_DECODE[loop].bitmap;
1445 switch (MIPS16_DECODE[loop].mark)
1446 {
1447 case I:
1448 case RI:
1449 case RRI:
1450 num = bitmap_val (bitmap, 11, 5);
1451 break;
1452 case ISHIFT:
1453 num = 32 + bitmap_val (bitmap, 0, 2);
1454 break;
1455 case RRI_A:
1456 num = 36 + bitmap_val (bitmap, 4, 1);
1457 break;
1458 case I8:
1459 case I8_MOV32R:
1460 case I8_MOVR32:
1461 num = 38 + bitmap_val (bitmap, 8, 3);
1462 break;
1463 case RRR:
1464 num = 46 + bitmap_val (bitmap, 0, 2);
1465 break;
1466 case RR:
1467 {
1468 int minor;
1469
1470 minor = bitmap_val (bitmap, 0, 5);
1471 if (minor != 0)
1472 num = 50 + minor;
1473 else
1474 num = 90 + bitmap_val (bitmap, 5, 3);
1475 }
1476 break;
1477 case I64:
1478 case RI64:
1479 num = 82 + bitmap_val (bitmap, 8, 3);
1480 break;
1481 default:
1482 abort ();
1483 }
8ad57737 1484
831f59a2
ILT
1485 printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
1486 bitmap);
8ad57737 1487
831f59a2 1488 printf (" {\n");
8ad57737 1489
831f59a2 1490 build_mips16_operands (bitmap);
8ad57737 1491
831f59a2 1492 printf (" {\n") ;
8ad57737 1493
831f59a2
ILT
1494 /* build_instruction doesn't know about extend. */
1495 if (num != 30)
1496 build_instruction (doisa, features, 1, &MIPS16_DECODE[loop]);
1497 else
1498 {
1499 printf (" extendval = ext;\n");
1500 printf (" have_extendval = 1;\n");
1501 }
8ad57737 1502
831f59a2
ILT
1503 printf (" }\n");
1504 printf (" }\n") ;
1505 printf (" break ;\n") ;
1506 }
8ad57737 1507
831f59a2
ILT
1508 printf ("default : /* Unrecognised instruction */\n") ;
1509 printf (" SignalException(ReservedInstruction,instruction);\n") ;
1510 printf (" break ;\n") ;
1511 printf ("}\n}\n") ;
8ad57737 1512
831f59a2 1513 printf("#endif /* simulator engine */\n");
8ad57737 1514
831f59a2
ILT
1515 return ;
1516}
8ad57737 1517
831f59a2
ILT
1518/* Output the code to execute an instruction, assuming the operands
1519 have already been extracted. */
8ad57737 1520
831f59a2
ILT
1521static void
1522build_instruction (doisa, features, mips16, insn)
1523 int doisa;
1524 unsigned int features;
1525 int mips16;
1526 const struct instruction *insn;
1527{
1528 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
1529 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1530 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
1531
1532 switch (insn->type) {
1533 /* TODO: To make these easier to edit and maintain, they should
1534 actually be provided as source macros (or inline functions)
1535 OUTSIDE this main switch statement. The PPC simulator has a
1536 neater scheme for describing the instruction sequences. */
1537
1538 case ADD:
1539 case SUB:
1540 {
1541 char *signed_basetype = "unknown";
1542 char *unsigned_basetype = "unknown";
1543
1544 switch (GETDATASIZEINSN(insn)) {
1545 case WORD :
1546 signed_basetype = "signed int";
1547 unsigned_basetype = "unsigned int";
1548 break;
1549 case DOUBLEWORD :
1550 signed_basetype = "word64";
1551 unsigned_basetype = "uword64";
1552 break;
1553 default :
1554 fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn));
1555 exit(1);
1556 }
8ad57737 1557
831f59a2
ILT
1558 if ((insn->type) == ADD) {
1559 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
1560 printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
1561 if (insn->flags & OVERFLOW) {
1562 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
1563 printf(" SignalException(IntegerOverflow);\n");
1564 printf(" else\n");
1565 }
1566 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
1567 printf(" GPR[destreg] = (%s)temp;\n",regtype);
1568 else /* only sign-extend when placing 32bit result in 64bit processor */
1569 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
1570 } else { /* SUB */
1571 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype);
1572 printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
1573 if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
1574 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
1575 printf(" SignalException(IntegerOverflow);\n");
1576 printf(" else\n");
1577 }
1578 /* UNSIGNED 32bit operations on a 64bit processor should
1579 *STILL* be sign-extended. We have cheated in the
1580 data-structure, by not marking it with UNSIGNED, and not
1581 setting OVERFLOW. */
1582 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
1583 printf(" GPR[destreg] = (%s)temp;\n",regtype);
1584 else /* only sign-extend when placing 32bit result in 64bit processor */
1585 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
1586 }
1587 }
1588 break ;
8ad57737 1589
831f59a2
ILT
1590 case MUL:
1591 if (features & FEATURE_WARN_LOHI) {
1592 printf(" CHECKHILO(\"Multiplication\");\n");
1593 }
1594 printf(" {\n");
1595 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
1596 printf(" uword64 mid;\n");
1597 printf(" uword64 midhi;\n");
1598 printf(" uword64 temp;\n");
1599 if ((insn->flags & UNSIGNED) == 0)
1600 {
1601 printf(" int sign = 0;\n");
1602 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
1603 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
1604 }
1605 printf(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
1606 printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
1607 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
1608 printf(" midhi = SET64HI(WORD64LO(mid));\n");
1609 printf(" temp = (LO + midhi);\n");
1610 printf(" if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n");
1611 printf(" HI += 1;\n");
1612 printf(" HI += WORD64HI(mid);\n");
1613 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
1614 printf(" midhi = SET64HI(WORD64LO(mid));\n");
1615 printf(" LO = (temp + midhi);\n");
1616 printf(" if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n");
1617 printf(" HI += 1;\n");
1618 printf(" HI += WORD64HI(mid);\n");
1619 if ((insn->flags & UNSIGNED) == 0)
1620 printf(" if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n");
1621 } else {
1622 if (insn->flags & UNSIGNED)
1623 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
1624 else
1625 printf(" uword64 temp = (op1 * op2);\n");
1626 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
1627 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
1628 }
1629 printf(" }\n");
1630 break ;
8ad57737 1631
831f59a2
ILT
1632 case DIV:
1633 {
1634 int boolU = (insn->flags & UNSIGNED);
8ad57737 1635
831f59a2
ILT
1636 if (features & FEATURE_WARN_LOHI) {
1637 printf(" CHECKHILO(\"Division\");\n");
1638 }
1639 printf(" {\n");
1640 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
1641 printf(" LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
1642 printf(" HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU ? "u" : ""),'%',(boolU ? "u" : ""));
1643 } else {
1644 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
1645 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
1646 }
1647 printf(" }\n");
1648 }
1649 break ;
1650
1651 case SHIFT:
1652 {
1653 int datalen = GETDATASIZEINSN(insn);
1654 int bits = ((datalen == WORD) ? 32 : 64);
1655 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
1656
1657 /* Check that the specified SHIFT is valid: */
1658 if ((datalen == BYTE) || (datalen == HALFWORD)) {
1659 fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn->name);
1660 exit(9);
1661 }
1662 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
1663 fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn->name);
1664 exit(9);
1665 }
1666 if (!(insn->flags & LEFT) && !(insn->flags & RIGHT)) {
1667 fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn->name);
1668 exit(9);
1669 }
1670 if ((insn->flags & LOGICAL) && (insn->flags & ARITHMETIC)) {
1671 fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn->name);
1672 exit(9);
1673 }
1674 if (!(insn->flags & LOGICAL) && !(insn->flags & ARITHMETIC)) {
1675 fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn->name);
1676 exit(9);
1677 }
1678 if ((insn->flags & LEFT) && (insn->flags & ARITHMETIC)) {
1679 fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",insn->name);
1680 exit(9);
1681 }
8ad57737 1682
831f59a2
ILT
1683 /* If register specified shift, then extract the relevant shift amount: */
1684 if (insn->flags & REG)
1685 printf(" op1 &= 0x%02X;\n",(bits - 1));
1686
1687 /* If HI32 specified, then shift range is 32..63 */
1688 if (insn->flags & HI32)
1689 printf(" op1 |= (1 << 5);\n");
1690
1691 /* We do not need to perform pre-masking with 0xFFFFFFFF when
1692 dealing with 32bit shift lefts, since the sign-extension
1693 code will replace any remaining hi-bits: */
1694 if (insn->flags & LEFT)
1695 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
1696 else
1697 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
1698
1699 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
1700 don't do this if op1 is zero, since it is not needed and
1701 since that would cause an undefined shift of the number of
1702 bits in the type. */
1703 if (insn->flags & ARITHMETIC)
1704 printf(" GPR[destreg] |= (op1 != 0 && (op2 & ((%s)1 << %d)) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,(bits - 1),ltype,bits);
1705
1706 /* Ensure WORD values are sign-extended into 64bit registers */
1707 if ((bits == 32) && (gprlen == 64))
1708 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
1709 }
1710 break ;
1711
1712 case MOVE:
1713 if (insn->flags & (HI | LO)) {
1714 char *regname = ((insn->flags & LO) ? "LO" : "HI");
1715 if (insn->flags & LEFT)
1716 printf(" GPR[destreg] = %s;\n",regname);
1717 else {
1718 if (features & FEATURE_WARN_LOHI) {
1719 printf(" if (%sACCESS != 0)\n",regname);
1720 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname);
1721 }
1722 printf(" %s = op1;\n",regname);
1723 }
1724 if (features & FEATURE_WARN_LOHI)
1725 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
1726 } else
1727 if (insn->flags & SHIFT16)
1728 printf(" GPR[destreg] = (op2 << 16);\n");
1729 else {
1730 /* perform conditional move */
1731 if (!(insn->flags & EQ)) {
1732 fprintf(stderr,"Standard conditional %s does not have the equality flag\n",insn->name);
1733 exit(8);
1734 }
1735 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
1736 printf(" GPR[destreg] = op1;\n");
1737 }
1738 break ;
1739
1740 case SYNC:
1741 printf(" SyncOperation(op1);\n");
1742 break ;
1743
1744 case SYSCALL:
1745 printf(" SignalException(SystemCall,instruction);\n");
1746 break ;
1747
1748 case BREAK:
1749 printf(" SignalException(BreakPoint,instruction);\n");
1750 break ;
1751
1752 case TRAP:
1753 {
1754 int boolNOT = (insn->flags & NOT);
1755 int boolEQ = (insn->flags & EQ);
1756 int boolGT = (insn->flags & GT);
1757 int boolLT = (insn->flags & LT);
1758 int boolU = (insn->flags & UNSIGNED);
1759
1760 if (boolGT && boolLT) {
1761 fprintf(stderr,"GT and LT specified for \"%s\"\n",insn->name);
1762 exit(8);
1763 }
8ad57737 1764
831f59a2
ILT
1765 if (boolNOT && (boolGT || boolLT)) {
1766 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",insn->name);
1767 exit(8);
1768 }
8ad57737 1769
831f59a2
ILT
1770 printf(" if ((%sword64)op1 ",(boolU ? "u" : ""));
1771 printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
1772 printf(" (%sword64)op2)\n",(boolU ? "u" : ""));
1773 printf(" SignalException(Trap,instruction);\n");
1774 }
1775 break ;
8ad57737 1776
831f59a2
ILT
1777 case SET:
1778 {
1779 int boolU = (insn->flags & UNSIGNED);
8ad57737 1780
831f59a2
ILT
1781 if (!(insn->flags & LT)) {
1782 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",insn->name);
1783 exit(8);
1784 }
8ad57737 1785
831f59a2
ILT
1786 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
1787 printf(" GPR[destreg] = 1;\n");
1788 printf(" else\n");
1789 printf(" GPR[destreg] = 0;\n");
1790 }
1791 break ;
1792
1793 case AND:
1794 printf(" GPR[destreg] = (op1 & op2);\n");
1795 break ;
1796
1797 case OR:
1798 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn->flags & NOT) ? "~" : ""));
1799 break ;
1800
1801 case XOR:
1802 printf(" GPR[destreg] = (op1 ^ op2);\n");
1803 break ;
1804
1805 case DECODE:
1806 printf(" decode_coproc(instruction);\n");
1807 break ;
1808
1809 case CACHE:
1810 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1811 /* The virtual address is translated to a physical address using the TLB */
1812 /* The hint specifies a cache operation for that address */
1813 printf(" uword64 vaddr = (op1 + offset);\n");
1814 printf(" uword64 paddr;\n");
1815 printf(" int uncached;\n");
1816 /* NOTE: We are assuming that the AddressTranslation is a load: */
1817 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1818 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1819 break;
1820
1821 case MADD16: /* VR4100 specific multiply-add instructions */
1822 /* Some of this code is shared with the standard multiply
1823 routines, so an effort should be made to merge where
1824 possible. */
1825 if (features & FEATURE_WARN_LOHI) {
1826 printf(" CHECKHILO(\"Multiply-Add\");\n");
1827 }
1828 if (features & FEATURE_WARN_RESULT) {
1829 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1830 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1831 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
1832 }
1833 printf(" {\n");
1834 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1835 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
1836 printf(" LO = LO + temp;\n");
1837 } else { /* WORD */
1838 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
1839 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
1840 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
1841 }
1842 printf(" }\n");
1843 break;
1844
1845 case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1846 if (doisa < 4) {
1847 printf(" if (CoProcPresent(3))\n");
1848 printf(" SignalException(CoProcessorUnusable);\n");
1849 printf(" else\n");
1850 }
1851 printf(" SignalException(ReservedInstruction,instruction);\n");
1852 break ;
1853
1854 case JUMP:
1855 if (insn->flags & LINK) {
1856 if (!(insn->flags & REG))
1857 printf(" int destreg = 31;\n");
1858 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
1859 mips16 ? 2 : 4, mips16 ? 2 : 4);
1860 }
8ad57737 1861
831f59a2
ILT
1862 if (insn->flags & NOT)
1863 printf(" op1 ^= 1;\n");
8ad57737 1864
6429b296
JW
1865 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
1866 printf(" so we just truncate it to 32 bits here. */\n");
1867 printf(" op1 = WORD64LO(op1);\n");
831f59a2
ILT
1868 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1869 printf(" DSPC = op1;\n");
aaff8437
ILT
1870 if (insn->flags & LINK)
1871 printf(" JALDELAYSLOT();\n");
1872 else
1873 printf(" DELAYSLOT();\n");
831f59a2 1874 break ;
8ad57737 1875
831f59a2
ILT
1876 case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1877 if (insn->flags & FP) {
1878 if (doisa < 4) {
1879 printf(" if (condition_code != 0)\n");
1880 printf(" SignalException(ReservedInstruction,instruction);\n");
1881 printf(" else {\n");
1882 }
1883 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
1884 printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
1885 } else {
1886 if ((insn->flags & NOT) && !(insn->flags & EQ)) {
1887 fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",insn->name);
1888 exit(7);
1889 }
1890 if ((insn->flags & NOT) && (insn->flags & (GT | LT))) {
1891 fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",insn->name);
1892 exit(7);
1893 }
1894 /* GT LT */
1895 if (insn->flags & GT)
1896 printf(" int condition = (op1 >%s 0);\n",((insn->flags & EQ) ? "=" : ""));
1897 else
1898 if (insn->flags & LT)
1899 printf(" int condition = (op1 <%s 0);\n",((insn->flags & EQ) ? "=" : ""));
1900 else
1901 if (insn->flags & EQ)
1902 printf(" int condition = (op1 %c= op2);\n",((insn->flags & NOT) ? '!' : '='));
1903 }
8ad57737 1904
831f59a2
ILT
1905 if (insn->flags & LINK) {
1906 if (features & FEATURE_WARN_R31) {
1907 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS);
1908 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
1909 }
1910 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1911 }
8ad57737 1912
831f59a2
ILT
1913 if (! mips16) {
1914 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1915 printf(" if (condition) {\n");
1916 printf(" DSPC = (PC + offset);\n");
1917 printf(" DELAYSLOT();\n");
1918 printf(" }\n");
1919 } else {
1920 /* No delayed slots for mips16 branches. */
1921 printf(" if (condition)\n");
1922 printf(" PC = PC + offset;\n");
1923 }
1924 if ((insn->flags & FP) && (doisa != 1)) {
1925 printf(" else if (likely) {\n");
1926 printf(" NULLIFY();\n");
1927 printf(" }\n");
1928 } else if (insn->flags & LIKELY) {
1929 printf(" else\n");
1930 printf(" NULLIFY();\n");
1931 }
1932 if ((insn->flags & FP) && (doisa < 4))
1933 printf(" }\n");
1934 break ;
1935
1936 case PREFETCH: /* The beginning is shared with normal load operations */
1937 case LOAD:
1938 case STORE:
1939 {
1940 int isload = ((insn->type == LOAD) || (insn->type == PREFETCH));
1941 int datalen;
1942 char *accesslength = "<UNKNOWN>";
1943
1944 switch (GETDATASIZEINSN(insn)) {
1945 case BYTE :
1946 datalen = 1;
1947 accesslength = "AccessLength_BYTE";
1948 break ;
1949
1950 case HALFWORD :
1951 datalen = 2;
1952 accesslength = "AccessLength_HALFWORD";
1953 break ;
1954
1955 case WORD :
1956 datalen = 4;
1957 accesslength = "AccessLength_WORD";
1958 break ;
1959
1960 case DOUBLEWORD :
1961 datalen = 8;
1962 accesslength = "AccessLength_DOUBLEWORD";
1963 break ;
1964 }
8ad57737 1965
831f59a2
ILT
1966 if (insn->flags & REG)
1967 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
1968 else
1969 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
1970 printf(" uword64 paddr;\n");
1971 printf(" int uncached;\n");
1972
1973 /* The following check should only occur on normal (non-shifted) memory loads */
1974 if ((datalen != 1) && !(insn->flags & (LEFT | RIGHT))) {
1975 printf(" if ((vaddr & %d) != 0)\n",(datalen - 1));
1976 printf(" SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
1977 printf(" else\n") ;
1978 }
1979
1980 printf(" {\n");
1981 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
1982
1983 if (insn->type == PREFETCH)
1984 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1985 else {
1986 printf(" {\n");
1987 printf(" %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
1988
1989 if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
1990 fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
1991 exit(6);
1992 }
8ad57737 1993
831f59a2
ILT
1994 if (insn->flags & (LEFT | RIGHT)) {
1995 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
1996 fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn->name);
1997 exit(4);
1998 }
1999
2000 switch (datalen) {
2001 case 8:
2002 if (!proc64) {
2003 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
2004 exit(4);
2005 }
2006 /* fall through to... */
2007 case 4:
2008 {
2009 printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
2010 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2011 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2012 printf(" int byte;\n");
2013 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2014 printf(" byte = ((vaddr & mask) ^ bigend);\n");
51c6d733 2015 printf(" if (%s!ByteSwapMem)\n",((insn->flags & LEFT) ? "!" : ""));
831f59a2
ILT
2016 printf(" paddr &= ~mask;\n");
2017
2018 if (isload) {
2019 if (insn->flags & LEFT)
2020 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2021 else
2022 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
2023 }
2024
2025 if (insn->flags & LEFT) {
2026 if (isload) {
2027 /* For WORD transfers work out if the value will
2028 be in the top or bottom of the DOUBLEWORD
2029 returned: */
e871dd18 2030#if 1
831f59a2 2031 build_endian_shift(proc64,datalen,2,s_right,32);
e871dd18 2032#else
831f59a2
ILT
2033 if (proc64 && (datalen == 4)) {
2034 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2035 printf(" memval >>= 32;\n");
2036 printf(" }\n");
2037 }
e871dd18 2038#endif
831f59a2
ILT
2039 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
2040 if (proc64 && (datalen == 4))
2041 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2042 } else { /* store */
2043 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
e871dd18 2044#if 1
831f59a2 2045 build_endian_shift(proc64,datalen,2,s_left,32);
e871dd18 2046#else
831f59a2
ILT
2047 /* TODO: This is duplicated in the LOAD code
2048 above - and the RIGHT LOAD and STORE code
2049 below. It should be merged if possible. */
2050 if (proc64 && (datalen == 4)) {
2051 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2052 printf(" memval <<= 32;\n");
2053 printf(" }\n");
2054 }
e871dd18 2055#endif
831f59a2
ILT
2056 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
2057 }
2058 } else { /* RIGHT */
2059 if (isload) {
e871dd18 2060#if 1
831f59a2 2061 build_endian_shift(proc64,datalen,2,s_right,32);
e871dd18 2062#else
831f59a2
ILT
2063 if (proc64 && (datalen == 4)) {
2064 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2065 printf(" memval >>= 32;\n");
2066 printf(" }\n");
2067 }
e871dd18 2068#endif
831f59a2
ILT
2069 printf(" {\n");
2070 printf(" uword64 srcmask;\n");
2071 /* All of this extra code is just a bodge
2072 required because some hosts don't allow
2073 ((v) << 64). The SPARC just leaves the (v)
2074 value un-touched. */
2075 printf(" if (byte == 0)\n");
2076 printf(" srcmask = 0;\n");
2077 printf(" else\n");
2078 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
2079 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2080 printf(" }\n");
2081 if (proc64 && (datalen == 4))
2082 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2083 } else { /* store */
2084 printf(" memval = (op2 << (byte * 8));\n");
2085 build_endian_shift(proc64,datalen,2,s_left,32);
2086 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength);
2087 }
2088 }
2089 }
2090 break;
2091
2092 default:
2093 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
2094 exit(6);
2095 }
2096 } else { /* normal memory transfer */
2097 if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
2098 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
2099 exit(4);
2100 /* TODO: The R4000 documentation states that a LWU
2101 instruction executed when in a 32bit processor mode
2102 should cause a ReservedInstruction exception. This
2103 will mean adding a run-time check into the code
2104 sequence. */
2105 }
2106
2107 if (isload) {
c98ec95d 2108#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2109 printf(" uword64 mask = 0x7;\n");
c98ec95d 2110#else
831f59a2 2111 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2112#endif
831f59a2
ILT
2113 printf(" unsigned int shift = %d;\n",(datalen >> 1));
2114 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2115 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2116 printf(" unsigned int byte;\n");
8ad57737 2117
c98ec95d 2118/* TODO: This should really also check for 32bit world performing 32bit access */
831f59a2
ILT
2119 if (datalen != 8) /* not for DOUBLEWORD */
2120 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2121
2122 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
2123
2124 /* The following will only make sense if the
2125 "LoadMemory" above returns a DOUBLEWORD entity */
2126 if (datalen != 8) { /* not for DOUBLEWORD */
2127 int valmask;
2128 switch (datalen) {
2129 case 1:
2130 valmask = 0xFF;
2131 break;
2132
2133 case 2:
2134 valmask = 0xFFFF;
2135 break;
2136
2137 case 4:
2138 valmask = 0xFFFFFFFF;
2139 break;
2140
2141 default:
2142 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,insn->name);
2143 exit(4);
2144 }
2145 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2146 /* NOTE: The R4000 user manual has the COP_LW
2147 occuring in the same cycle as the rest of the
2148 instruction, yet the MIPS IV shows the operation
2149 happening on the next cycle. To keep the simulator
2150 simple, this code follows the R4000
2151 manual. Experimentation with a silicon
2152 implementation will be needed to ascertain the
2153 correct operation. */
2154 if (insn->flags & COPROC)
2155 printf(" COP_LW(%s,destreg,(unsigned int)",
2156 ((insn->flags & REG)
2157 ? "1"
2158 : "((instruction >> 26) & 0x3)"));
2159 else
2160 printf(" GPR[destreg] = (");
2161
2162 if (insn->flags & SIGNEXTEND)
2163 printf("SIGNEXTEND(");
2164 printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
2165 if (insn->flags & SIGNEXTEND)
2166 printf(",%d)",(datalen * 8));
2167 printf(");\n");
2168 } else {
2169 if (insn->flags & COPROC)
2170 printf(" COP_LD(%s,destreg,memval);;\n",
2171 ((insn->flags & REG)
2172 ? "1"
2173 : "((instruction >> 26) & 0x3)"));
2174 else
2175 printf(" GPR[destreg] = memval;\n");
2176 }
2177 } else { /* store operation */
2178 if ((datalen == 1) || (datalen == 2)) {
2179 /* SH and SB */
c98ec95d 2180#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2181 printf(" uword64 mask = 0x7;\n");
c98ec95d 2182#else
831f59a2 2183 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2184#endif
831f59a2
ILT
2185 printf(" unsigned int shift = %d;\n",(datalen >> 1));
2186 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2187 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2188 printf(" unsigned int byte;\n");
2189
2190 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2191 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2192 printf(" memval = (op2 << (8 * byte));\n");
2193 } else
2194 if (proc64 && (datalen == 4)) { /* proc64 SC and SW */
c98ec95d 2195#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2196 printf(" uword64 mask = 0x7;\n");
c98ec95d 2197#else
831f59a2 2198 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2199#endif
831f59a2
ILT
2200 printf(" unsigned int byte;\n");
2201 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2202 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2203 if (insn->flags & COPROC)
2204 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2205 ((insn->flags & REG)
2206 ? "1"
2207 : "((instruction >> 26) & 0x3)"),
2208 ((insn->flags & FP) ? "fs" : "destreg"));
2209 else
2210 printf(" memval = (op2 << (8 * byte));\n");
2211 } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
2212 if (insn->flags & COPROC)
2213 printf(" memval = (uword64)COP_S%c(%s,%s);\n",
2214 ((datalen == 8) ? 'D' : 'W'),
2215 ((insn->flags & REG)
2216 ? "1"
2217 : "((instruction >> 26) & 0x3)"),
2218 ((insn->flags & FP) ? "fs" : "destreg"));
2219 else
2220 printf(" memval = op2;\n");
2221 }
2222
2223 if (insn->flags & ATOMIC)
2224 printf(" if (LLBIT)\n");
2225
2226 printf(" {\n");
2227 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
2228 printf(" }\n");
2229 }
2230
2231 if (insn->flags & ATOMIC) {
2232 if ((datalen != 4) && (datalen != 8)) {
2233 fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn->name);
2234 exit(4);
2235 } else
2236 if (isload)
2237 printf(" LLBIT = 1;\n");
2238 else {
2239 /* The documentation states that:
2240
2241 SC *WILL* fail if coherent store into the same
2242 block occurs, or if an exception occurs between
2243 the LL and SC instructions.
2244
2245 SC *MAY* fail if a load, store or prefetch is
2246 executed on the processor (VR4300 doesn't seem
2247 to), or if the instructions between the LL and
2248 SC are not in a 2048byte contiguous VM range.
2249
2250 SC *MUST* have been preceded by an LL
2251 (i.e. LLBIT will be set), and it must use the
2252 same Vaddr, Paddr and cache-coherence algorithm
2253 as the LL (which means we should store this
2254 information from the load-conditional).
2255 */
2256 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
2257 }
2258 }
2259 }
2260 printf(" }\n");
8ad57737 2261 }
831f59a2
ILT
2262 printf(" }\n");
2263 }
2264 break ;
2265
2266 case FPPREFX:
2267 /* This code could be merged with the PREFIX generation above: */
2268 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2269 printf(" uword64 paddr;\n");
2270 printf(" int uncached;\n");
2271 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2272 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2273 break ;
2274
2275 case FPMOVEC:
2276 if (insn->flags & CONTROL) {
2277 /* The following "magic" of interpreting the FP
2278 control-register number would not be needed if we were not
2279 trying to match our internal register numbers with those
2280 used by GDB. */
2281 printf(" if (to) {\n");
2282 if (doisa < 4) {
2283 printf(" if (fs == 0) {\n");
2284 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2285 printf(" } else if (fs == 31) {\n");
2286 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2287 printf(" } /* else NOP */\n");
2288 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2289 } else {
2290 printf(" if (fs == 0) {\n");
2291 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2292 printf(" } else if (fs == 31) {\n");
2293 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2294 printf(" } /* else NOP */\n");
2295 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2296 }
2297 printf(" } else { /* control from */\n");
2298 if (doisa < 4) {
2299 printf(" if (fs == 0) {\n");
2300 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2301 printf(" } else if (fs == 31) {\n");
2302 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2303 printf(" } /* else NOP */\n");
2304 } else {
2305 printf(" if (fs == 0) {\n");
2306 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2307 printf(" } else if (fs == 31) {\n");
2308 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2309 printf(" } /* else NOP */\n");
2310 }
2311 printf(" }\n");
2312 } else {
2313 printf(" if (to) {\n");
2314 if (GETDATASIZEINSN(insn) == WORD) {
2315 if (doisa < 4) {
2316 printf(" if (SizeFGR() == 64) {\n");
2317 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
2318 printf(" } else { \n");
2319 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2320 printf(" }\n");
2321 } else {
2322 printf(" if (SizeFGR() == 64)\n");
2323 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
2324 printf(" else\n");
2325 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
2326 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2327 }
2328 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2329 if (doisa < 4) {
2330 printf(" if (SizeFGR() == 64) {\n");
2331 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
2332 printf(" } else\n");
2333 printf(" if ((fs & 0x1) == 0)\n");
2334 printf(" {\n");
2335 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
2336 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2337 printf(" }\n");
2338 if (features & FEATURE_WARN_RESULT) {
2339 printf(" else\n");
2340 printf(" UndefinedResult();\n");
2341 }
2342 } else {
2343 printf(" if (SizeFGR() == 64) {\n");
2344 printf(" FGR[fs] = GPR[ft];\n");
2345 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2346 printf(" } else\n");
2347 printf(" if ((fs & 0x1) == 0)\n");
2348 printf(" {\n");
2349 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
2350 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
2351 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
2352 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2353 printf(" }\n");
2354 if (features & FEATURE_WARN_RESULT) {
2355 printf(" else\n");
2356 printf(" UndefinedResult();\n");
2357 }
2358 }
2359 } else {
2360 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
2361 exit(1);
2362 }
2363 printf(" } else {\n");
2364 if (GETDATASIZEINSN(insn) == WORD) {
2365 if (doisa < 4) /* write-back occurs in next cycle */
2366 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
2367 else /* in this cycle */
2368 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
2369 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2370 if (doisa < 4) {
2371 printf(" if (SizeFGR() == 64) {\n");
2372 printf(" PENDING_FILL(ft,FGR[fs]);\n");
2373 printf(" } else\n");
2374 printf(" if ((fs & 0x1) == 0) {\n");
2375 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
2376 printf(" } else {\n");
2377 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
2378 if (features & FEATURE_WARN_RESULT)
2379 printf(" UndefinedResult();\n");
2380 printf(" }\n");
2381 } else {
2382 printf(" if (SizeFGR() == 64)\n");
2383 printf(" GPR[ft] = FGR[fs];\n");
2384 printf(" else\n");
2385 printf(" if ((fs & 0x1) == 0)\n");
2386 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
2387 printf(" else {\n");
2388 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
2389 if (features & FEATURE_WARN_RESULT)
2390 printf(" UndefinedResult();\n");
2391 printf(" }\n");
2392 }
2393 } else {
2394 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
2395 exit(1);
2396 }
2397 printf(" }\n");
2398 }
2399 break ;
2400
2401 case FPMOVE:
2402 if (insn->flags & CONDITIONAL) {
2403 if (insn->flags & INTEGER) { /* moving GPR - testing FGR */
2404 printf(" if (GETFCC(condition_code) == boolean)\n");
2405 printf(" GPR[destreg] = op1;\n");
2406 } else {
2407 if (insn->flags & EQ) /* moving FGR - testing GPR */
2408 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
2409 else
2410 printf(" if (GETFCC(condition_code) == boolean)\n");
2411 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
2412 printf(" else\n");
2413 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
2414 }
2415 } else { /* simple MOVE */
2416 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
2417 }
2418 break ;
2419
2420 case FPNEG:
2421 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2422 printf(" SignalException(ReservedInstruction,instruction);\n");
2423 printf(" else\n");
2424 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
2425 break ;
2426
2427 case FPABS:
2428 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2429 printf(" SignalException(ReservedInstruction,instruction);\n");
2430 printf(" else\n");
2431 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
2432 break ;
2433
2434 case FPDIV:
2435 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2436 printf(" SignalException(ReservedInstruction,instruction);\n");
2437 printf(" else\n");
2438 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2439 break ;
2440
2441 case FPMUL:
2442 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2443 printf(" SignalException(ReservedInstruction,instruction);\n");
2444 printf(" else\n");
2445 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2446 break ;
2447
2448 case FPRECIP:
2449 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2450 printf(" SignalException(ReservedInstruction,instruction);\n");
2451 printf(" else\n");
2452 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
2453 break ;
2454
2455 case FPSQRT:
2456 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2457 printf(" SignalException(ReservedInstruction,instruction);\n");
2458 printf(" else\n");
2459 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn->flags & RECIP) ? "Recip" : ""));
2460 break ;
2461
2462 case FPCEIL:
2463 case FPFLOOR:
2464 case FPTRUNC:
2465 case FPROUND:
2466 {
2467 char *op = "";
2468 char *type = "";
2469
2470 switch (insn->type) {
2471 case FPCEIL:
2472 op = "FP_RM_TOPINF";
2473 break;
2474 case FPFLOOR:
2475 op = "FP_RM_TOMINF";
2476 break;
2477 case FPTRUNC:
2478 op = "FP_RM_TOZERO";
2479 break;
2480 case FPROUND:
2481 op = "FP_RM_NEAREST";
2482 break;
2483 default:
2484 fprintf(stderr,"Error: Handled missing for FP reason code %d\n",insn->type);
2485 exit(1);
2486 }
8ad57737 2487
831f59a2
ILT
2488 switch (GETDATASIZEINSN(insn)) {
2489 case WORD :
2490 type = "fmt_word";
2491 break;
2492 case DOUBLEWORD :
2493 type = "fmt_long";
2494 break;
2495 default:
2496 fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
2497 exit(1);
2498 }
2499 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2500 printf(" SignalException(ReservedInstruction,instruction);\n");
2501 printf(" else\n");
2502 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
2503 }
2504 break ;
2505
2506 case FPCONVERT:
2507 {
2508 char *type = "";
2509 switch (GETDATASIZEINSN(insn)) {
2510 case SINGLE:
2511 type = "fmt_single";
2512 break;
2513 case DOUBLE:
2514 type = "fmt_double";
2515 break;
2516 case WORD:
2517 type = "fmt_word";
2518 break;
2519 case DOUBLEWORD:
2520 type = "fmt_long";
2521 break;
2522 default :
2523 fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn));
2524 exit(1);
2525 }
8ad57737 2526
831f59a2
ILT
2527 /* Not all combinations of conversion are valid at the
2528 moment: When converting to a fixed-point format, only
2529 floating-point sources are allowed. */
2530 printf(" if ((format == %s) | %s)\n",type,((insn->flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
2531 printf(" SignalException(ReservedInstruction,instruction);\n");
2532 printf(" else\n");
2533 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
2534 }
2535 break ;
2536
2537 case FPSUB:
2538 if (insn->flags & MULTIPLY) {
2539 char *type = "";
2540 switch (GETDATASIZEINSN(insn)) {
2541 case SINGLE:
2542 type = "fmt_single";
2543 break;
2544 case DOUBLE:
2545 type = "fmt_double";
2546 break;
2547 default:
2548 fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn));
2549 exit(1);
2550 }
2551 printf(" StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type,((insn->flags & NOT) ? "Negate" : ""),type,type,type,type,type,type);
2552 } else {
2553 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2554 printf(" SignalException(ReservedInstruction,instruction);\n");
2555 printf(" else\n");
2556 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2557 }
2558 break ;
2559
2560 case FPADD:
2561 if (insn->flags & MULTIPLY) {
2562 char *type = "";
2563 switch (GETDATASIZEINSN(insn)) {
2564 case SINGLE:
2565 type = "fmt_single";
2566 break;
2567 case DOUBLE:
2568 type = "fmt_double";
2569 break;
2570 default:
2571 fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn));
2572 exit(1);
2573 }
2574 if (insn->flags & NOT)
2575 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
2576 type, type, type, type, type, type, type);
2577 else
2578 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
2579 type, type, type, type, type, type);
2580 } else {
2581 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2582 printf(" SignalException(ReservedInstruction,instruction);\n");
2583 printf(" else\n");
2584 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2585 }
2586 break ;
2587
2588 case FPCOMPARE:
2589 /* For the MIPS I,II or III there *MUST* be at least one
2590 instruction between the compare that sets a condition code
2591 and the branch that tests it. NOTE: However the hardware
2592 does not detect this condition. */
2593 /* Explicitly limit the operation to S and D formats: */
2594 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2595 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2596 printf(" else {\n");
2597 if (doisa < 4) {
2598 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
2599 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2600 printf(" else\n");
2601 }
2602 printf(" {\n");
2603 printf(" int ignore = 0;\n");
2604 printf(" int less = 0;\n");
2605 printf(" int equal = 0;\n");
2606 printf(" int unordered = 1;\n");
2607 printf(" uword64 ofs = ValueFPR(fs,format);\n");
2608 printf(" uword64 oft = ValueFPR(ft,format);\n");
2609 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
2610 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
2611 printf(" FCSR |= FP_CAUSE(IO);\n");
2612 printf(" SignalException(FPE);\n");
2613 printf(" ignore = 1;\n");
2614 printf(" }\n");
2615 printf(" } else {\n");
2616 printf(" less = Less(ofs,oft,format);\n");
2617 printf(" equal = Equal(ofs,oft,format);\n");
2618 printf(" unordered = 0;\n");
2619 printf(" }\n");
2620 printf(" if (!ignore) {\n");
2621 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
2622 printf(" SETFCC(condition_code,condition);\n");
2623 printf(" }\n");
2624 printf(" }\n");
2625 printf(" }\n");
2626 break ;
2627
2628 default:
2629 fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
2630 exit(6) ;
2631 }
8ad57737
JSC
2632}
2633
2634/*---------------------------------------------------------------------------*/
2635
2636/* The command-line feature controls are presented in a similar style
2637 to those offered by GCC, in the aim of providing a consistent
2638 interface to the user. */
2639typedef enum {
2640 T_NONE, /* no argument - mask and value fields control "feature" definition */
2641 T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
2642 T_STRING /* string argument - optionally prcededed by '=' */
2643} mactypes;
2644
2645struct {
2646 char *name;
2647 mactypes type;
2648 unsigned int mask;
2649 unsigned int value;
2650 char *desc;
2651} machine_options[] = {
2652 {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"},
2653 {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"},
2654 {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"},
2655 {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"},
2656 {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"},
8ad57737
JSC
2657 {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"},
2658 {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"},
2659 {0, T_NONE, 0,0}
2660};
2661
2662/* The following architecture identies are those accepted by the "-mcpu" option: */
2663struct architectures {
2664 const char *name; /* ASCII string identifier for command-line, no white-space allowed */
2665 unsigned int idflag; /* or-ed into "isa" value */
2666};
2667
2668static const struct architectures available_architectures[] = {
2669 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
2670 {0, 0} /* terminator */
2671};
2672
2673/*---------------------------------------------------------------------------*/
2674
2675static void
2676usage(name)
2677 char *name;
2678{
2679 int loop;
2680
2681 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
2682
2683 fprintf(stderr,"\
2684The output of this program is a block of 'C' code designed to be\n\
2685included into the main simulation control loop of a device specific\n\
2686simulator.\n");
2687
2688 fprintf(stderr,"\nOptions:\n");
2689 fprintf(stderr," -h --help\t\tProvide this help text\n");
2690 fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
2691 fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n");
2692
2693 for (loop = 0; (machine_options[loop].name != 0); loop++) {
2694 fprintf(stderr," -m%s",machine_options[loop].name);
2695 switch (machine_options[loop].type) {
2696 case T_NUM :
2697 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
2698 case T_NONE :
2699 break;
2700
2701 case T_STRING :
2702 fprintf(stderr,"=name");
2703 break;
2704
2705 default :
831f59a2 2706 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type);
8ad57737
JSC
2707 exit(1);
2708 }
2709 fprintf(stderr,"%s\n",machine_options[loop].desc);
2710 }
2711
2712 fprintf(stderr,"\nAvailable \"-mcpu\" architectures: ");
2713 for (loop = 0; (available_architectures[loop].name != 0); loop++)
2714 fprintf(stderr,"%s ",available_architectures[loop].name);
2715 fprintf(stderr,"\n\n");
2716
2717 fprintf(stderr,"\
2718The \"trace\" and \"warnings\" options do not define the output stream.\n\
2719They only inform the code that includes the constructed engine to provide\n\
2720the required features.\n\n\
2721The \"-mips0\" option forces the construction of a simulator supporting\n\
2722the highest available MIPS ISA supported.\n");
2723
2724 return;
2725}
2726
2727/*---------------------------------------------------------------------------*/
2728
2729int
2730main(argc,argv)
2731 int argc;
2732 char **argv;
2733{
2734 int c;
2735 char *progname = argv[0];
2736 unsigned int doarch = DEF_ISA;
2737 unsigned int features = 0; /* default state */
2738
2739 if (DEF_FP)
2740 features |= FEATURE_HASFPU;
2741 if (!DEF_PROC64)
2742 features |= FEATURE_PROC32;
2743 if (DEF_FPSINGLE)
2744 features |= FEATURE_FPSINGLE;
2745
2746 if (features & FEATURE_PROC32)
8bae0a0c 2747 features &= ~FEATURE_GP64;
8ad57737 2748 else
8bae0a0c 2749 features |= FEATURE_GP64;
8ad57737
JSC
2750
2751 while (1) {
8ad57737
JSC
2752 int option_index = 0;
2753 static struct option cmdline[] = {
2754 {"fast", 0,0,'f'},
2755 {"help", 0,0,'h'},
2756 {"warnings",0,0,'w'},
2757 {0, 0,0,0}
2758 };
2759
2760 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
2761 if (c == -1)
2762 break ; /* out of the while loop */
2763
2764 switch (c) {
2765 case 'h' : /* help */
2766 usage(progname);
2767 exit(0);
2768
2769 case 'f' : /* fast */
2770 features |= FEATURE_FAST;
2771 break;
2772
2773 case 'w' : /* warnings */
2774 features |= FEATURE_WARNINGS;
2775 /* TODO: Future extension: Allow better control over the warnings generated:
2776 disable warnings -wnone ~FEATURE_WARNINGS
2777 all possible warnings -wall FEATURE_WARNINGS
2778 pipeline stall occuring -wstall FEATURE_WARN_STALL
2779 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
2780 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
2781 bad r31 use -wr31 FEATURE_WARN_R31
2782 undefined results -wresult FEATURE_WARN_RESULT
2783 */
2784 break;
2785
2786 case 'm' : /* machine options */
2787 {
2788 int loop;
2789
2790 for (loop = 0; (machine_options[loop].name != 0); loop++)
2791 if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) {
2792 char *loptarg = (optarg + strlen(machine_options[loop].name));
2793 switch (machine_options[loop].type) {
2794 case T_NONE :
2795 if (*loptarg) {
2796 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
2797 exit(1);
2798 }
2799 features &= ~(machine_options[loop].mask);
2800 features |= machine_options[loop].value;
2801 break;
2802
2803 case T_NUM :
2804 if (*loptarg && *loptarg == '=')
2805 loptarg++;
2806
2807 if (strcmp(machine_options[loop].name,"ips") == 0) {
2808 unsigned int num;
2809
2810 if (!*loptarg) {
2811 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
2812 exit(1);
2813 }
2814
64d538ce 2815 num = my_strtoul(loptarg,&loptarg,10);
8ad57737
JSC
2816
2817 if ((num == ULONG_MAX) && (errno = ERANGE)) {
2818 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
2819 exit(1);
2820 }
2821
2822 if (*loptarg) {
2823 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
2824 exit(1);
2825 }
2826
2827 if (num > MASK_ISA) {
2828 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
2829 exit(1);
2830 }
2831
2832 doarch = ((doarch & ~MASK_ISA) | num);
2833 if ((num == 0) || (num > 2)) {
8bae0a0c
JSC
2834 if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64))
2835 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num);
2836 features |= FEATURE_GP64;
8ad57737
JSC
2837 features &= ~FEATURE_PROC32;
2838 } else {
8bae0a0c
JSC
2839 if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64))
2840 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num);
2841 features &= ~FEATURE_GP64;
8ad57737
JSC
2842 features |= FEATURE_PROC32;
2843 }
2844 } else {
2845 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
2846 exit(1);
2847 }
2848 break;
2849
2850 case T_STRING :
2851 if (*loptarg && *loptarg == '=')
2852 loptarg++;
2853
2854 if (strcmp(machine_options[loop].name,"cpu") == 0) {
2855 int archloop;
2856
2857 if (!*loptarg) {
2858 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
2859 exit(1);
2860 }
2861
2862 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
2863 if ((*loptarg == 'v') || (*loptarg == 'V'))
831f59a2 2864 loptarg++;
8ad57737 2865
831f59a2
ILT
2866 if ((*loptarg == 'r') || (*loptarg == 'R'))
2867 loptarg++;
8ad57737
JSC
2868
2869 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
2870 doarch |= available_architectures[archloop].idflag;
2871 break;
2872 }
2873 }
2874
2875 if (available_architectures[archloop].name == 0) {
2876 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
2877 exit(1);
2878 }
2879 } else {
2880 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
2881 exit(1);
2882 }
2883 break;
2884
2885 default :
2886 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
2887 exit(1);
2888 }
2889 break;
2890 }
2891
2892 if (machine_options[loop].name == 0) {
2893 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
2894 exit(1);
2895 }
2896 }
2897 break;
2898
2899 case '?' :
2900 /* An error message should already have been displayed */
2901 exit(1);
2902
2903 default :
2904 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
2905 exit(1);
2906 }
2907 }
2908
2909 if (optind < argc) {
2910 fprintf(stderr,"%s: Spurios non-option arguments ",progname);
2911 while (optind < argc)
2912 fprintf(stderr,"\"%s\" ",argv[optind++]);
2913 fprintf(stderr,"\n");
2914 exit(1);
2915 }
2916
2917 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
2918 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
2919
2920 process_instructions(doarch,features) ;
2921 return(0) ;
2922}
2923
2924/*---------------------------------------------------------------------------*/
64d538ce
ILT
2925
2926/* We can't assume that the compiler for the build system has strtoul,
2927 so we provide our own copy. */
2928
2929/*
2930 * Copyright (c) 1990 Regents of the University of California.
2931 * All rights reserved.
2932 *
2933 * Redistribution and use in source and binary forms, with or without
2934 * modification, are permitted provided that the following conditions
2935 * are met:
2936 * 1. Redistributions of source code must retain the above copyright
2937 * notice, this list of conditions and the following disclaimer.
2938 * 2. Redistributions in binary form must reproduce the above copyright
2939 * notice, this list of conditions and the following disclaimer in the
2940 * documentation and/or other materials provided with the distribution.
2941 * 3. All advertising materials mentioning features or use of this software
2942 * must display the following acknowledgement:
2943 * This product includes software developed by the University of
2944 * California, Berkeley and its contributors.
2945 * 4. Neither the name of the University nor the names of its contributors
2946 * may be used to endorse or promote products derived from this software
2947 * without specific prior written permission.
2948 *
2949 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2950 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2951 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2952 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2953 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2954 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2955 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2956 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2957 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2958 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2959 * SUCH DAMAGE.
2960 */
2961
2962/*
2963 * Convert a string to an unsigned long integer.
2964 *
2965 * Ignores `locale' stuff. Assumes that the upper and lower case
2966 * alphabets and digits are each contiguous.
2967 */
2968static unsigned long
2969my_strtoul(nptr, endptr, base)
2970 const char *nptr;
2971 char **endptr;
2972 register int base;
2973{
2974 register const char *s = nptr;
2975 register unsigned long acc;
2976 register int c;
2977 register unsigned long cutoff;
2978 register int neg = 0, any, cutlim;
2979
2980 /*
2981 * See strtol for comments as to the logic used.
2982 */
2983 do {
2984 c = *s++;
2985 } while (isspace(c));
2986 if (c == '-') {
2987 neg = 1;
2988 c = *s++;
2989 } else if (c == '+')
2990 c = *s++;
2991 if ((base == 0 || base == 16) &&
2992 c == '0' && (*s == 'x' || *s == 'X')) {
2993 c = s[1];
2994 s += 2;
2995 base = 16;
2996 }
2997 if (base == 0)
2998 base = c == '0' ? 8 : 10;
2999 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
3000 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
3001 for (acc = 0, any = 0;; c = *s++) {
3002 if (isdigit(c))
3003 c -= '0';
3004 else if (isalpha(c))
3005 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
3006 else
3007 break;
3008 if (c >= base)
3009 break;
831f59a2 3010 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
64d538ce
ILT
3011 any = -1;
3012 else {
3013 any = 1;
3014 acc *= base;
3015 acc += c;
3016 }
3017 }
3018 if (any < 0) {
3019 acc = ULONG_MAX;
3020 errno = ERANGE;
3021 } else if (neg)
3022 acc = -acc;
3023 if (endptr != 0)
3024 *endptr = (char *) (any ? s - 1 : nptr);
3025 return (acc);
3026}
3027
3028/*---------------------------------------------------------------------------*/
3029
8ad57737 3030/*> EOF gencode.c <*/
This page took 0.20336 seconds and 4 git commands to generate.