gencode.c: Two arg MADD should not assign result to /bin/bash.
[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
ae19b07b
JL
120/* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
121 have the zero register as a destination -- the zero register just doesn't
122 actually change. */
123/* start-sanitize-r5900 */
124/* The 5900 madd instructions for example use this feature. */
125/* end-sanitize-r5900 */
8bae0a0c 126#if 1
ae19b07b 127#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31)
8bae0a0c 128#else
ae19b07b 129#define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
8bae0a0c 130#endif
8ad57737
JSC
131
132/* FEATURE_WARN_STALL */
133/* If MIPS I we want to raise a warning if an attempt is made to
134 access Rn in an instruction immediately following an Rn update
135 "WARNING : Invalid value read". The simulator engine is designed
136 that the previous value is read in such cases, to allow programs
831f59a2 137 that make use of this feature to execute. */
8ad57737
JSC
138/* If MIPS II or later, attempting to read a register before the
139 update has completed will generate a "WARNING : Processor stall"
140 message (since the processor will lock the pipeline until the value
141 becomes available). */
142
143/* FEATURE_WARN_LOHI */
144/* Warn if an attempt is made to read the HI/LO registers before the
145 update has completed, or if an attempt is made to update the
146 registers whilst an update is occurring. */
147
148/* FEATURE_WARN_ZERO */
149/* Notify the user if an attempt is made to use GPR 0 as a destination. */
150
151/* FEATURE_WARN_R31 */
152/* Notify the user if register r31 (the default procedure call return
153 address) is used unwisely. e.g. If r31 is used as the source in a
154 branch-and-link instruction, it would mean that an exception in the
155 delay slot instruction would not allow the branch to be re-started
156 (since r31 will have been overwritten by the link operation during
157 the first execution of the branch). */
158
159/* FEATURE_WARN_RESULT */
160/* Certain instructions do not raise exceptions when invalid operands
161 are given, they will just result in undefined values being
162 generated. This option controls whether the simulator flags such
163 events. */
164
165/*---------------------------------------------------------------------------*/
166
167#include <stdio.h>
168#include <getopt.h>
169#include <limits.h>
170#include <errno.h>
64d538ce
ILT
171#include <ctype.h>
172#include "ansidecl.h"
8bae0a0c 173#include "opcode/mips.h"
8ad57737 174
64d538ce
ILT
175/* FIXME: ansidecl.h defines AND. */
176#undef AND
8bae0a0c 177
64d538ce
ILT
178#ifndef ULONG_MAX
179#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
180#endif
8bae0a0c 181
64d538ce 182static unsigned long my_strtoul ();
8ad57737 183
8bae0a0c 184#if 0
8ad57737
JSC
185#ifndef TRUE
186#define TRUE (1 == 1)
187#define FALSE (1 == 0)
188#endif
8bae0a0c 189#endif
8ad57737
JSC
190
191/*---------------------------------------------------------------------------*/
192
193/* Holding the instruction table this way makes it easier to check the
194 instruction values defined, and to add instructions to the
195 system. However, it makes the process of constructing the simulator
196 a bit more complicated: */
197
198/* The "bitmap" is encoded as follows (NOTE: Only lower-case
199 alphabetic characters should be used, since the letter ordinal is
200 used as a bit position): */
201
202typedef struct operand_encoding {
203 char id; /* character identifier */
204 int fpos; /* first bit position */
205 int flen; /* field length in bits */
206 char * const type;
207 char * const name;
208 unsigned int flags;
209} operand_encoding;
210
211/* Values for the "flags" field: */
212#define OP_NONE (0 << 0) /* To keep the source tidy */
213#define OP_GPR (1 << 0) /* Get operand from integer register bank */
8bae0a0c
JSC
214#define OP_SIGNX (1 << 1) /* Sign-extend the operand */
215#define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
216#define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
276c2d7d 217#define OP_GPR1 (1 << 4) /* fetch from the GPR1 registers */
8ad57737
JSC
218
219struct operand_encoding opfields[] = {
8bae0a0c
JSC
220 {'0',-1,-1,"", "", (OP_NONE)}, /* special case for explicit zero */
221 {'1',-1,-1,"", "", (OP_NONE)}, /* special case for explicit one */
222 {'?',-1,-1,"", "", (OP_NONE)}, /* undefined (do not care at this level) */
8ad57737 223 /* The rest are the explicit operand fields: */
8bae0a0c
JSC
224 {'a', 6, 5,"int", "op1", (OP_NONE)}, /* shift amount (or hint) */
225 {'b',21, 5,"int", "fr", (OP_NONE)}, /* fr register */
226 {'c',16, 1,"int", "boolean", (OP_NONE)}, /* TRUE or FALSE boolean */
227 {'d',11, 5,"int", "destreg", (OP_NONE)}, /* integer destination/rd register */
228 {'e', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-3bits must be zero) */
229 {'f',17, 1,"int", "likely", (OP_NONE)}, /* set if branch LIKELY */
230 {'g',16, 5,"t_reg", "op2", (OP_GPR)}, /* integer source rt register */
231 {'h', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-1bit must be zero) */
232 {'i', 0,16,"t_reg", "op2", (OP_SIGNX)}, /* signed immediate (op2) */
233 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
234 {'k',16, 5,"int", "ft", (OP_NONE)},
235 {'l', 0,16,"t_reg", "offset", (OP_SIGNX | OP_SHIFT2)}, /* signed offset shifted left 2 to make 18bit signed offset */
236 {'m',21, 3,"int", "format", (OP_NONE)}, /* FP format field */
237 {'n',16, 5,"int", "hint", (OP_NONE)}, /* hint */
238 {'o',21, 5,"t_reg", "op1", (OP_GPR | OP_BITS5)}, /* integer source/rs register (but never treated as 32bit word) */
239 {'p', 8, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
240 {'q',18, 3,"int", "condition_code",(OP_NONE)}, /* FP condition code field */
241 {'r', 6, 5,"int", "destreg", (OP_NONE)}, /* FP fd register */
242 {'s',21, 5,"t_reg", "op1", (OP_GPR)}, /* integer source/rs register */
243 {'t',16, 5,"int", "destreg", (OP_NONE)}, /* integer target rt (destination) register */
244 {'u', 0, 4,"int", "cmpflags", (OP_NONE)}, /* FP comparison control flags */
245 {'v',11, 5,"int", "fs", (OP_NONE)}, /* FP fs register (or PREFX hint) */
246 {'w', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset (lo-2bits must be zero) */
247 {'x',23, 1,"int", "to", (OP_NONE)}, /* TRUE if move To; FALSE if move From */
248 {'y', 0,16,"t_reg", "offset", (OP_SIGNX)}, /* signed offset */
249 {'z', 0,16,"ut_reg","op2", (OP_NONE)}, /* unsigned immediate (zero extended) */
276c2d7d
GRK
250 {'S',21, 5,"t_reg", "rs_reg", (OP_GPR|OP_GPR1)}, /* rs field, GPR[rs] and GPR1[rs] as source */
251 {'T',16, 5,"t_reg", "rt_reg", (OP_GPR|OP_GPR1)}, /* rt field, GPR[rt] and GPR1[rt] as source */
8ad57737
JSC
252};
253
276c2d7d 254
8ad57737
JSC
255/* Main instruction encoding types: */
256typedef enum {
257 NORMAL,
258 SPECIAL,
259 REGIMM,
260 COP1,
261 COP1X,
8bae0a0c 262 COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
831f59a2 263
276c2d7d
GRK
264 MMINORM,
265 MMI0,
266 MMI1,
267 MMI2,
268 MMI3,
269
831f59a2
ILT
270 /* mips16 encoding types. */
271 I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64
8ad57737
JSC
272} inst_type;
273
274/* Main instruction families: */
275typedef enum {
276 ADD, /* res = operand1 + operand2 */
277 SUB, /* res = operand1 - operand2 */
278 MUL, /* res = operand1 * operand2 */
279 DIV, /* res = operand1 / operand2 */
280 AND, /* res = operand1 & operand2 */
281 OR, /* res = operand1 | operand2 */
282 XOR, /* res = operand1 ^ operand2 */
283 MOVE, /* res = operand1 */
284 BRANCH, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
285 JUMP, /* execute delay slot instruction before jump */
286 LOAD, /* load from memory */
287 STORE, /* store to memory */
288 PREFETCH, /* prefetch data into cache */
289 SET, /* set register on result of condition code */
290 SHIFT, /* perform a logical or arithmetic shift */
291 TRAP, /* system exception generation */
292 BREAK, /* system breakpoint exception generation */
293 SYSCALL, /* system exception generation */
294 SYNC, /* system cache control */
295 DECODE, /* co-processor instruction */
296 CACHE, /* co-processor 0 CACHE instruction */
297 MADD16, /* VR4100 specific multiply-add extensions */
298 FPMOVE,
8bae0a0c 299 FPMOVEC,
8ad57737
JSC
300 FPFLOOR,
301 FPCEIL,
302 FPTRUNC,
303 FPROUND,
304 FPNEG,
305 FPABS,
306 FPDIV,
307 FPMUL,
308 FPSUB,
309 FPADD,
8ad57737 310 FPPREFX,
8ad57737
JSC
311 FPRECIP,
312 FPSQRT,
313 FPCONVERT,
314 FPCOMPARE,
276c2d7d
GRK
315 /* start-sanitize-r5900 */
316 MADD,
317 PABS,
318 PADD,
319 PADSBH,
320 POP,
321 PCMP,
322 PCPYH,
323 PCPYLD,
324 PCPYUD,
325 PEXCH,
326 PEXCW,
327 PEXOH,
328 PEXOW,
329 PEXTLB,
330 PEXTLH,
331 PEXTLW,
332 PEXTUB,
333 PEXTUH,
334 PEXTUW,
335 PPACB,
336 PPACH,
337 PPACW,
338 PREVH,
339 PROT3W,
340 PINTH,
341 PINTOH,
342 PMXX,
343 PMFHL,
344 PMTHL,
345 PMAXMIN,
346 QFSRV,
347 MxSA,
348 MTSAB,
349 MTSAH,
350 PSHIFT,
351 PSLLVW,
352 PSRLVW,
353 PSRAVW,
354 PLZCW,
355 PHMADDH,
356 PMULTH,
357 PMULTW,
358 PDIVBW,
359 PDIVW,
360 PEXT5,
361 PPAC5,
362 /* end-sanitize-r5900 */
363 NYI, /* Not Yet Implemented, placeholder, errors if used */
8ad57737
JSC
364 RSVD /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
365} opcode_type;
366
367/* Flags field: */
368#define NONE (0 << 0) /* Zero value (used to keep source tidy) */
369#define SIM_SH_SIZE (0)
8bae0a0c
JSC
370#define SIM_MASK_SIZE (0x7)
371#define BYTE (0) /* 8bit */
372#define HALFWORD (1) /* 16bit */
373#define WORD (2) /* 32bit */
374#define DOUBLEWORD (3) /* 64bit */
375#define SINGLE (4) /* single precision FP */
376#define DOUBLE (5) /* double precision FP */
276c2d7d 377#define QUADWORD (6) /* 128bit */
8ad57737
JSC
378
379/* Shorthand to get the size field from the flags value: */
831f59a2 380#define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
8ad57737
JSC
381
382/* The rest are single bit flags: */
8ad57737
JSC
383#define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
384#define EQ (1 << 4)
385#define GT (1 << 5)
386#define LT (1 << 6)
387#define NOT (1 << 7)
388#define LIKELY (1 << 8)
389#define SIGNEXTEND (1 << 9)
390#define OVERFLOW (1 << 10)
391#define LINK (1 << 11)
392#define ATOMIC (1 << 12)
393#define SHIFT16 (1 << 13)
394#define REG (1 << 14)
395#define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
396#define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
397#define LOGICAL (1 << 17)
398#define ARITHMETIC (1 << 18)
399#define UNSIGNED (1 << 19)
400#define HI32 (1 << 20)
401#define HI (1 << 21) /* accesses or updates the HI register */
402#define LO (1 << 22) /* accesses or updates the LO register */
403#define WORD32 (1 << 23)
404#define FP (1 << 24) /* Floating Point operation */
405#define FIXED (1 << 25) /* fixed point arithmetic */
8bae0a0c
JSC
406#define COPROC (1 << 26)
407#define INTEGER (1 << 27)
408#define CONDITIONAL (1 << 28)
409#define RECIP (1 << 29)
410#define CONTROL (1 << 30)
8ad57737 411#define NOARG (1 << 31) /* Instruction has no (defined) operands */
8bae0a0c
JSC
412/* NOTE: We can overload the use of certain of these flags, since not
413 all options are applicable to all instruction types. This will free
414 up more space for new flags. */
8ad57737 415
276c2d7d
GRK
416/* Overloadings of above bits */
417#define PIPE1 LIKELY /* Using pipeline 1 (DIV,MUL) */
418#define OP3 EQ /* 3 operand version of operation (MUL) */
419
420#define SATURATE OVERFLOW /* for PADD, saturate for overflow */
421
422#define SUBTRACT LEFT /* for PMULT, PMULT becomes PMSUB */
423#define ADDITION RIGHT /* for PMULT, PMULT becomes PMADD */
424
425#define FROM LEFT /* move from special register */
426#define TO RIGHT /* move to special register */
427
428/* For bitwise parallel operations */
c94db67a
GRK
429#define POP_AND 0 /* for POP, op = & */
430#define POP_OR LEFT /* for POP, op = | */
431#define POP_NOR LIKELY /* for POP, op = ~(x | y) */
432#define POP_XOR LEFT|LIKELY /* for POP, op = ^ */
433
434#define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
435
276c2d7d 436
276c2d7d 437
8ad57737
JSC
438typedef struct instruction {
439 char *name; /* ASCII mnemonic name */
440 unsigned int isa; /* MIPS ISA number where instruction introduced */
441 char *bitmap; /* 32character string describing instruction operands */
442 inst_type mark; /* type of MIPS instruction encoding */
443 opcode_type type; /* main instruction family */
444 unsigned int flags; /* flags describing instruction features */
445} instruction;
446/* The number of pipeline cycles taken by an instruction varies
447 between MIPS processors. This means that the information must be
448 encoded elsewhere, in a CPU specific structure. */
449
450/* NOTE: Undefined instructions cause "Reserved Instruction"
451 exceptions. i.e. if there is no bit-mapping defined then the
452 instruction is deemed to be undefined. */
453
454/* NOTE: The "isa" field is also used to encode flags for particular
455 chip architecture extensions. e.g. the NEC VR4100 specific
456 instructions. Normally chip extensions are added via the COP0
457 space. However, the VR4100 (and possibly other devices) also use
458 the normal instruction space. */
459#define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
460/* The other bits are allocated downwards, to avoid renumbering if we
528031fd
GRK
461 have to extend the bits allocated to the pure ISA number.
462
463 These architecture bits come in two flavors:
464 ISA dependent - marking insns that should be included in the opcode
465 set if that architecture is requested on the gencode command line
466 AND the ISA of the insn is <= requested ISA;
467
468 ISA independent - marking insn that should be included in the opcode
469 set if that architecture is requested
470 OR the ISA of the insn is <= requested ISA.
471
472 Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
473 */
8ad57737 474#define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
276c2d7d
GRK
475/* start-sanitize-r5900 */
476#define ARCH_R5900 ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
477/* end-sanitize-r5900 */
478
479/* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
480#define MASK_ISA_INDEP (0 \
481 /* start-sanitize-r5900 */ \
482 | ARCH_R5900 \
483 /* end-sanitize-r5900 */ \
484 | 0)
485
528031fd 486#define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
276c2d7d
GRK
487
488
489/* Very short names for use in the table below to keep it neet. */
490#define G1 (3 | ARCH_VR4100)
491
492#define G2 (4 \
493 /* start-sanitize-r5900 */ \
494 | ARCH_R5900 \
495 /* end-sanitize-r5900 */ \
496 | 0)
497
498#define G3 (4 \
499 /* start-sanitize-r5900 */ \
500 /* insn that are not really 5900 insn but were left in */ \
501 /* until we can rewrite the code-gen and libs */ \
502 | ARCH_R5900 \
503 /* end-sanitize-r5900 */ \
504 | 0)
505
506
507
508/* start-sanitize-r5900 */
509#define T5 ARCH_R5900
510/* end-sanitize-r5900 */
511
8ad57737
JSC
512
513/* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
514 COP0 space. This means that an external decoder should be added
515 when constructing a full VR4100 simulator. However some arithmetic
516 instructions are encoded in the normal instruction space. */
517
518struct instruction MIPS_DECODE[] = {
519 /* The instructions are alphabetical, and not in instruction bit-order: */
a9f7253f 520 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1, FPABS, (FP)},
8ad57737 521 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL,ADD, (WORD | WORD32 | OVERFLOW)}, /* rd = rs + rt */
8bae0a0c 522 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1, FPADD, (FP)},
8ad57737
JSC
523 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32 | OVERFLOW)},
524 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL,ADD, (WORD | WORD32)}, /* rd = rs + rt */
525 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (WORD | WORD32)},
526 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL,AND, (NONE)}, /* rd = rs AND rt */
527 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND, (NONE)},
8bae0a0c 528 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S, BRANCH, (FP)},
8ad57737
JSC
529 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ)},
530 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH, (EQ | LIKELY)},
531 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH, (GT | EQ)},
532 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
533 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LINK)},
534 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM, BRANCH, (GT | EQ | LIKELY)},
535 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT)},
536 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL, BRANCH, (GT | LIKELY)},
537 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ)},
538 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL, BRANCH, (LT | EQ | LIKELY)},
539 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH, (LT)},
540 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH, (LT | LINK)},
541 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM, BRANCH, (LT | LINK | LIKELY)},
542 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM, BRANCH, (LT | LIKELY)},
543 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ)},
544 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH, (NOT | EQ | LIKELY)},
545 {"BREAK", 1,"000000????????????????????001101",SPECIAL,BREAK, (NOARG)},
546 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1, FPCEIL, (FP | FIXED | DOUBLEWORD)},
547 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1, FPCEIL, (FP | FIXED | WORD)},
548 {"COP0", 1,"010000??????????????????????????",NORMAL, DECODE, (NOARG)},
549 {"COP2", 1,"010010??????????????????????????",NORMAL, DECODE, (NOARG)},
550 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1, FPCONVERT,(FP | DOUBLE)},
551 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1, FPCONVERT,(FP | FIXED | DOUBLEWORD)},
552 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1, FPCONVERT,(FP | SINGLE)},
553 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1, FPCONVERT,(FP | FIXED | WORD)},
554 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1, FPCOMPARE,(FP)},
8bae0a0c 555 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD | CONTROL)},
8ad57737
JSC
556 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL,ADD, (DOUBLEWORD | OVERFLOW)},
557 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | OVERFLOW)},
558 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL,ADD, (DOUBLEWORD | UNSIGNED)},
559 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL, ADD, (DOUBLEWORD | UNSIGNED)},
560 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL,DIV, (DOUBLEWORD | HI | LO)},
561 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL,DIV, (DOUBLEWORD | UNSIGNED | HI | LO)},
562 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO)},
563 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1, FPDIV, (FP | WORD | HI | LO)},
276c2d7d
GRK
564 /* start-sanitize-r5900 */
565 {"DIV1", T5,"011100sssssggggg0000000000011010",MMINORM,DIV, (WORD | WORD32 | SIGNEXTEND | HI | LO | PIPE1)},
566 /* end-sanitize-r5900 */
8ad57737 567 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
276c2d7d
GRK
568 /* start-sanitize-r5900 */
569 {"DIVU1", T5,"011100sssssggggg0000000000011011",MMINORM,DIV, (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO | PIPE1)},
570 /* end-sanitize-r5900 */
571 {"DMADD16",G1,"000000sssssggggg0000000000101001",SPECIAL,MADD16, (DOUBLEWORD | HI | LO)},
8ad57737
JSC
572 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL,MUL, (DOUBLEWORD | HI | LO)},
573 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL,MUL, (DOUBLEWORD | UNSIGNED | HI | LO)},
8bae0a0c 574 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | DOUBLEWORD)},
8ad57737 575 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL)},
831f59a2 576 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | REG)},
8ad57737
JSC
577 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */
578 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
831f59a2 579 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | REG)},
8ad57737
JSC
580 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */
581 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
831f59a2 582 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | REG)},
8ad57737
JSC
583 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)},
584 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)},
585 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)},
586 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1, FPFLOOR, (FP | FIXED | DOUBLEWORD)},
587 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1, FPFLOOR, (FP | FIXED | WORD)},
588 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */
589 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */
590 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)},
831f59a2 591 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK | NOT)},
8ad57737
JSC
592 {"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */
593 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
594 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */
595 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD)},
596 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
597 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | COPROC)},
598 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | LEFT)}, /* NOTE: See "LB" comment */
599 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (DOUBLEWORD | RIGHT)}, /* NOTE: See "LB" comment */
276c2d7d 600 {"LDXC1", G3,"010011sssssggggg00000rrrrr000001",COP1X, LOAD, (FP | DOUBLEWORD | COPROC | REG)},
8ad57737
JSC
601 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD | SIGNEXTEND)},
602 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD, (HALFWORD)},
603 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | ATOMIC | SIGNEXTEND)},
604 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (DOUBLEWORD | ATOMIC)},
605 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE, (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
276c2d7d
GRK
606 /* start-sanitize-r5900 */
607 {"LQ", T5,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD, (QUADWORD)},
608 /* end-sanitize-r5900 */
8ad57737
JSC
609 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | SIGNEXTEND)},
610 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
611 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD | COPROC)},
612 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | LEFT)},
613 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (WORD | RIGHT)},
614 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD, (WORD)},
276c2d7d
GRK
615 {"LWXC1", G3,"010011sssssggggg00000rrrrr000000",COP1X, LOAD, (FP | WORD | COPROC | REG)},
616 /* start-sanitize-r5900 */
617 {"MADD", T5,"011100sssssgggggddddd00000000000",MMINORM,MADD, (NONE)},
618 {"MADD1", T5,"011100sssssgggggddddd00000100000",MMINORM,MADD, (PIPE1)},
619 {"MADDU", T5,"011100sssssgggggddddd00000000001",MMINORM,MADD, (UNSIGNED)},
620 {"MADDU1", T5,"011100sssssgggggddddd00000100001",MMINORM,MADD, (UNSIGNED | PIPE1)},
621 /* end-sanitize-r5900 */
622 {"MADD16", G1,"000000sssssggggg0000000000101000",SPECIAL,MADD16, (WORD | HI | LO)},
623 {"MADD.D", G3,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X, FPADD, (FP | MULTIPLY | DOUBLE)},
624 {"MADD.S", G3,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X, FPADD, (FP | MULTIPLY | SINGLE)},
831f59a2 625 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI | LEFT)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
276c2d7d
GRK
626 /* start-sanitize-r5900 */
627 {"MFHI1", T5,"0111000000000000ddddd00000010000",MMINORM,MOVE, (HI | LEFT | PIPE1)},
628 /* end-sanitize-r5900 */
831f59a2 629 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO | LEFT)},
276c2d7d
GRK
630 /* start-sanitize-r5900 */
631 {"MFLO1", T5,"0111000000000000ddddd00000010010",MMINORM,MOVE, (LO | LEFT | PIPE1)},
632 {"MFSA", T5,"0000000000000000ddddd00000101000",SPECIAL,MxSA, (FROM)},
633 /* end-sanitize-r5900 */
831f59a2 634 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI | RIGHT)},
276c2d7d
GRK
635 /* start-sanitize-r5900 */
636 {"MTHI1", T5,"011100sssss000000000000000010001",MMINORM,MOVE, (HI | RIGHT | PIPE1)},
637 /* end-sanitize-r5900 */
831f59a2 638 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO | RIGHT)},
276c2d7d
GRK
639 /* start-sanitize-r5900 */
640 {"MTLO1", T5,"011100sssss000000000000000010011",MMINORM,MOVE, (LO | RIGHT | PIPE1)},
641 {"MTSA", T5,"000000sssss000000000000000101001",SPECIAL,MxSA, (TO)},
642 {"MTSAB", T5,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM, MTSAB, (NONE)},
643 {"MTSAH", T5,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM, MTSAH, (NONE)},
644 /* end-sanitize-r5900 */
8ad57737 645 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1, FPMOVE, (FP)},
276c2d7d
GRK
646 {"MOVN", G2,"000000sssssgggggddddd00000001011",SPECIAL,MOVE, (NOT | EQ)},
647 {"MOVN", G2,"01000110mmmgggggvvvvvrrrrr010011",COP1, FPMOVE, (FP | NOT | EQ)},
648 {"MOV%c", G3,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE, (FP | CONDITIONAL | INTEGER)},
649 {"MOV%c", G3,"01000110mmmqqq0cvvvvvrrrrr010001",COP1, FPMOVE, (FP | CONDITIONAL)},
650 {"MOVZ", G2,"000000sssssgggggddddd00000001010",SPECIAL,MOVE, (EQ)},
651 {"MOVZ", G2,"01000110mmmgggggvvvvvrrrrr010010",COP1, FPMOVE, (FP | EQ)},
652 {"MSUB.D", G3,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X, FPSUB, (FP | MULTIPLY | DOUBLE)},
653 {"MSUB.S", G3,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X, FPSUB, (FP | MULTIPLY | SINGLE)},
8ad57737 654 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1, FPMUL, (FP | HI | LO)},
276c2d7d
GRK
655 {"MULT", 1,"000000sssssgggggddddd00000011000",SPECIAL,MUL, (OP3 | WORD | WORD32 | HI | LO)},
656 /* start-sanitize-r5900 */
657 {"MULT1", T5,"011100sssssgggggddddd00000011000",MMINORM,MUL, (OP3 | WORD | WORD32 | HI | LO | PIPE1)},
658 /* end-sanitize-r5900 */
659 {"MULTU", 1,"000000sssssgggggddddd00000011001",SPECIAL,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO)},
660 /* start-sanitize-r5900 */
661 {"MULTU1", T5,"011100sssssgggggddddd00000011001",MMINORM,MUL, (OP3 | WORD | WORD32 | UNSIGNED | HI | LO | PIPE1)},
662 /* end-sanitize-r5900 */
8bae0a0c
JSC
663 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S, FPMOVEC, (FP | WORD)},
664 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1, FPNEG, (FP)},
8ad57737
JSC
665 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X, FPADD, (FP | NOT | MULTIPLY | DOUBLE)},
666 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X, FPADD, (FP | NOT | MULTIPLY | SINGLE)},
667 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X, FPSUB, (FP | NOT | MULTIPLY | DOUBLE)},
668 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X, FPSUB, (FP | NOT | MULTIPLY | SINGLE)},
669 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL,OR, (NOT)},
670 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL,OR, (NONE)},
671 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR, (NONE)},
276c2d7d
GRK
672
673 /* start-sanitize-r5900 */
674 {"PABSH", T5,"01110000000TTTTTddddd00101101000",MMI1, PABS, (HALFWORD)},
675 {"PABSW", T5,"01110000000TTTTTddddd00001101000",MMI1, PABS, (WORD)},
676
677 {"PADDB", T5,"011100SSSSSTTTTTddddd01000001000",MMI0, PADD, (BYTE)},
678 {"PADDH", T5,"011100SSSSSTTTTTddddd00100001000",MMI0, PADD, (HALFWORD)},
679 {"PADDW", T5,"011100SSSSSTTTTTddddd00000001000",MMI0, PADD, (WORD)},
680
681 {"PADDSB", T5,"011100SSSSSTTTTTddddd11000001000",MMI0, PADD, (BYTE | SATURATE)},
682 {"PADDSH", T5,"011100SSSSSTTTTTddddd10100001000",MMI0, PADD, (HALFWORD | SATURATE)},
683 {"PADDSW", T5,"011100SSSSSTTTTTddddd10000001000",MMI0, PADD, (WORD | SATURATE)},
684
685 {"PADDUB", T5,"011100SSSSSTTTTTddddd11000101000",MMI1, PADD, (BYTE | UNSIGNED)},
686 {"PADDUH", T5,"011100SSSSSTTTTTddddd10100101000",MMI1, PADD, (HALFWORD | UNSIGNED)},
687 {"PADDUW", T5,"011100SSSSSTTTTTddddd10000101000",MMI1, PADD, (WORD | UNSIGNED)},
688
689 {"PADSBH", T5,"011100SSSSSTTTTTddddd00100101000",MMI1, PADSBH, (NONE)},
690
691 {"PAND", T5,"011100SSSSSTTTTTddddd10010001001",MMI2, POP, (POP_AND)},
692
693 {"PCEQB", T5,"011100SSSSSTTTTTddddd01010101000",MMI1, PCMP, (EQ | BYTE)},
694 {"PCEQH", T5,"011100SSSSSTTTTTddddd00110101000",MMI1, PCMP, (EQ | HALFWORD)},
695 {"PCEQW", T5,"011100SSSSSTTTTTddddd00010101000",MMI1, PCMP, (EQ | WORD)},
696
697 {"PCGTB", T5,"011100SSSSSTTTTTddddd01010001000",MMI0, PCMP, (GT | BYTE)},
698 {"PCGTH", T5,"011100SSSSSTTTTTddddd00110001000",MMI0, PCMP, (GT | HALFWORD)},
699 {"PCGTW", T5,"011100SSSSSTTTTTddddd00010001000",MMI0, PCMP, (GT | WORD)},
700
701 {"PCPYH", T5,"01110000000TTTTTddddd11011101001",MMI3, PCPYH, (NONE)},
702 {"PCPYLD", T5,"011100SSSSSTTTTTddddd01110001001",MMI2, PCPYLD, (NONE)},
703 {"PCPYUD", T5,"011100SSSSSTTTTTddddd01110101001",MMI3, PCPYUD, (NONE)},
704
705 {"PDIVBW", T5,"011100SSSSSTTTTT0000011101001001",MMI2, PDIVBW, (NONE)},
706 {"PDIVUW", T5,"011100SSSSSTTTTT0000001101101001",MMI3, PDIVW, (UNSIGNED)},
707 {"PDIVW", T5,"011100SSSSSTTTTT0000001101001001",MMI2, PDIVW, (NONE)},
708
709 {"PEXCH", T5,"01110000000TTTTTddddd11010101001",MMI3, PEXCH, (NONE)},
710 {"PEXCW", T5,"01110000000TTTTTddddd11110101001",MMI3, PEXCW, (NONE)},
711 {"PEXOH", T5,"01110000000TTTTTddddd11010001001",MMI2, PEXOH, (NONE)},
712 {"PEXOW", T5,"01110000000TTTTTddddd11110001001",MMI2, PEXOW, (NONE)},
713
714 {"PEXT5", T5,"01110000000TTTTTddddd11110001000",MMI0, PEXT5, (NONE)},
715
716 {"PEXTLB", T5,"011100SSSSSTTTTTddddd11010001000",MMI0, PEXTLB, (NONE)},
717 {"PEXTLH", T5,"011100SSSSSTTTTTddddd10110001000",MMI0, PEXTLH, (NONE)},
718 {"PEXTLW", T5,"011100SSSSSTTTTTddddd10010001000",MMI0, PEXTLW, (NONE)},
719 {"PEXTUB", T5,"011100SSSSSTTTTTddddd11010101000",MMI1, PEXTUB, (NONE)},
720 {"PEXTUH", T5,"011100SSSSSTTTTTddddd10110101000",MMI1, PEXTUH, (NONE)},
721 {"PEXTUW", T5,"011100SSSSSTTTTTddddd10010101000",MMI1, PEXTUW, (NONE)},
722
723 {"PHMADDH",T5,"011100SSSSSTTTTTddddd10001001001",MMI2, PHMADDH, (NONE)},
724 {"PHMSUBH",T5,"011100SSSSSTTTTTddddd10101001001",MMI2, PHMADDH, (SUBTRACT)},
725
726 {"PINTH", T5,"011100SSSSSTTTTTddddd01010001001",MMI2, PINTH, (NONE)},
727 {"PINTOH", T5,"011100SSSSSTTTTTddddd01010101001",MMI3, PINTOH, (NONE)},
728
729 {"PLZCW", T5,"011100SSSSS00000ddddd00000000100",MMINORM,PLZCW, (NONE)},
730
731 {"PMADDH", T5,"011100SSSSSTTTTTddddd10000001001",MMI2, PMULTH, (ADDITION)},
2d18fbc6 732 {"PMADDUW",T5,"011100SSSSSTTTTTddddd00000101001",MMI3, PMULTW, (ADDITION | UNSIGNED)},
276c2d7d
GRK
733 {"PMADDW", T5,"011100SSSSSTTTTTddddd00000001001",MMI2, PMULTW, (ADDITION)},
734
735 {"PMAXH", T5,"011100SSSSSTTTTTddddd00111001000",MMI0, PMAXMIN, (GT | HALFWORD)},
736 {"PMAXW", T5,"011100SSSSSTTTTTddddd00011001000",MMI0, PMAXMIN, (GT | WORD)},
737
738 {"PMFHI", T5,"0111000000000000ddddd01000001001",MMI2, PMXX, (HI|FROM)},
739 {"PMFLO", T5,"0111000000000000ddddd01001001001",MMI2, PMXX, (LO|FROM)},
740
741 {"PMFHL", T5,"0111000000000000dddddaaaaa110000",MMINORM,PMFHL, (NONE)},
742
743 {"PMINH", T5,"011100SSSSSTTTTTddddd00111101000",MMI1, PMAXMIN, (LT | HALFWORD)},
744 {"PMINW", T5,"011100SSSSSTTTTTddddd00011101000",MMI1, PMAXMIN, (LT | WORD)},
745
746 {"PMSUBH", T5,"011100SSSSSTTTTTddddd10100001001",MMI2, PMULTH, (SUBTRACT)},
747 {"PMSUBW", T5,"011100SSSSSTTTTTddddd00100001001",MMI2, PMULTW, (SUBTRACT)},
748
749 {"PMTHI", T5,"011100SSSSS000000000001000101001",MMI3, PMXX, (HI|TO)},
750 {"PMTLO", T5,"011100SSSSS000000000001001101001",MMI3, PMXX, (LO|TO)},
751
752{"PMTHL.LW",T5,"011100SSSSS000000000000000110001",MMINORM,PMTHL, (NONE)},
753
754 {"PMULTH", T5,"011100SSSSSTTTTTddddd11100001001",MMI2, PMULTH, (NONE)},
755 {"PMULTUW",T5,"011100SSSSSTTTTTddddd01100101001",MMI3, PMULTW, (UNSIGNED)},
756 {"PMULTW", T5,"011100SSSSSTTTTTddddd01100001001",MMI2, PMULTW, (NONE)},
757
758 {"PNOR", T5,"011100SSSSSTTTTTddddd10011101001",MMI3, POP, (POP_NOR)},
759 {"POR", T5,"011100SSSSSTTTTTddddd10010101001",MMI3, POP, (POP_OR)},
760
761 {"PPAC5", T5,"01110000000TTTTTddddd11111001000",MMI0, PPAC5, (NONE)},
762
763 {"PPACB", T5,"011100SSSSSTTTTTddddd11011001000",MMI0, PPACB, (NONE)},
764 {"PPACH", T5,"011100SSSSSTTTTTddddd10111001000",MMI0, PPACH, (NONE)},
765 {"PPACW", T5,"011100SSSSSTTTTTddddd10011001000",MMI0, PPACW, (NONE)},
766
767 {"PREVH", T5,"01110000000TTTTTddddd11011001001",MMI2, PREVH, (NONE)},
768 {"PROT3W", T5,"01110000000TTTTTddddd11111001001",MMI2, PROT3W, (NONE)},
769
770 {"PSLLH", T5,"01110000000TTTTTdddddaaaaa110100",MMINORM,PSHIFT, (LEFT | LOGICAL | HALFWORD)},
771 {"PSLLVW", T5,"011100SSSSSTTTTTddddd00010001001",MMI2, PSLLVW, (NONE)},
772 {"PSLLW", T5,"01110000000TTTTTdddddaaaaa111100",MMINORM,PSHIFT, (LEFT | LOGICAL | WORD)},
773
774 {"PSRAH", T5,"01110000000TTTTTdddddaaaaa110111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | HALFWORD)},
775 {"PSRAVW", T5,"011100SSSSSTTTTTddddd00011101001",MMI3, PSRAVW, (NONE)},
776 {"PSRAW", T5,"01110000000TTTTTdddddaaaaa111111",MMINORM,PSHIFT, (RIGHT | ARITHMETIC | WORD)},
777
778 {"PSRLH", T5,"01110000000TTTTTdddddaaaaa110110",MMINORM,PSHIFT, (RIGHT | LOGICAL | HALFWORD)},
779 {"PSRLVW", T5,"011100SSSSSTTTTTddddd00011001001",MMI2, PSRLVW, (NONE)},
780 {"PSRLW", T5,"01110000000TTTTTdddddaaaaa111110",MMINORM,PSHIFT, (RIGHT | LOGICAL | WORD)},
781
782 {"PSUBB", T5,"011100SSSSSTTTTTddddd01001001000",MMI0, PADD, (SUBTRACT | BYTE)},
783 {"PSUBH", T5,"011100SSSSSTTTTTddddd00101001000",MMI0, PADD, (SUBTRACT | HALFWORD)},
784 {"PSUBSB", T5,"011100SSSSSTTTTTddddd11001001000",MMI0, PADD, (SUBTRACT | SATURATE | BYTE )},
785 {"PSUBSH", T5,"011100SSSSSTTTTTddddd10101001000",MMI0, PADD, (SUBTRACT | SATURATE | HALFWORD)},
786 {"PSUBSW", T5,"011100SSSSSTTTTTddddd10001001000",MMI0, PADD, (SUBTRACT | SATURATE | WORD)},
787 {"PSUBUB", T5,"011100SSSSSTTTTTddddd11001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | BYTE)},
788 {"PSUBUH", T5,"011100SSSSSTTTTTddddd10101101000",MMI1, PADD, (SUBTRACT | UNSIGNED | HALFWORD)},
789 {"PSUBUW", T5,"011100SSSSSTTTTTddddd10001101000",MMI1, PADD, (SUBTRACT | UNSIGNED | WORD)},
790 {"PSUBW", T5,"011100SSSSSTTTTTddddd00001001000",MMI0, PADD, (SUBTRACT | WORD)},
791
792 {"PXOR", T5,"011100SSSSSTTTTTddddd10011001001",MMI2, POP, (POP_XOR)},
793 /* end-sanitize-r5900 */
794
795 {"PREF", G2,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
8bae0a0c 796 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X, FPPREFX, (FP)},
276c2d7d
GRK
797
798 /* start-sanitize-r5900 */
799 {"QFSRV", T5,"011100SSSSSTTTTTddddd11011101000",MMI1, QFSRV, (NONE)},
800 /* end-sanitize-r5900 */
801
8ad57737
JSC
802 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1, FPRECIP, (FP)},
803 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1, FPROUND, (FP | FIXED | DOUBLEWORD)},
804 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1, FPROUND, (FP | FIXED | WORD)},
8bae0a0c 805 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1, FPSQRT, (FP | RECIP)},
8ad57737
JSC
806 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (BYTE)},
807 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | ATOMIC)},
808 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | ATOMIC)},
809 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD)},
810 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
811 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE, (DOUBLEWORD | COPROC)},
812 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | LEFT)},
813 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (DOUBLEWORD | RIGHT)},
276c2d7d 814 {"SDXC1", G3,"010011sssssgggggvvvvv00000001001",COP1X, STORE, (FP | DOUBLEWORD | COPROC | REG)},
8ad57737
JSC
815 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE, (HALFWORD)},
816 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
817 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT, (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
818 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL,SET, (LT)},
819 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT)},
820 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL,SET, (LT | UNSIGNED)},
821 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET, (LT | UNSIGNED)},
276c2d7d
GRK
822 /* start-sanitize-r5900 */
823 {"SQ", T5,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL, STORE, (QUADWORD)},
824 /* end-sanitize-r5900 */
8ad57737 825 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1, FPSQRT, (FP)},
8bae0a0c
JSC
826 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
827 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | ARITHMETIC)},
828 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
829 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL,SHIFT, (WORD | WORD32 | RIGHT | LOGICAL)},
8ad57737
JSC
830 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL,SUB, (WORD | WORD32 | OVERFLOW)},
831 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1, FPSUB, (FP)},
832 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL,SUB, (WORD | WORD32)},
833 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD)},
834 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
835 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE, (WORD | COPROC)},
836 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | LEFT)},
837 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE, (WORD | RIGHT)},
276c2d7d 838 {"SWXC1", G3,"010011sssssgggggvvvvv00000001000",COP1X, STORE, (FP | WORD | COPROC | REG)},
8ad57737
JSC
839 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL,SYNC, (NONE)}, /* z = 5bit stype field */
840 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL, (NOARG)},
841 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL,TRAP, (EQ)},
842 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP, (EQ)},
843 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL,TRAP, (GT | EQ)},
844 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ)},
845 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM, TRAP, (GT | EQ | UNSIGNED)},
846 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL,TRAP, (GT | EQ | UNSIGNED)},
847 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL,TRAP, (LT)},
848 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT)},
849 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM, TRAP, (LT | UNSIGNED)},
850 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL,TRAP, (LT | UNSIGNED)},
851 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL,TRAP, (NOT | EQ)},
852 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM, TRAP, (NOT | EQ)},
853 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1, FPTRUNC, (FP | FIXED | DOUBLEWORD)},
854 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1, FPTRUNC, (FP | FIXED | WORD)},
855 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL,XOR, (NONE)},
856 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR, (NONE)},
857 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE, (NONE)},
858 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD, (NONE)},
859};
860
831f59a2
ILT
861static const struct instruction MIPS16_DECODE[] = {
862{"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 },
863{"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 },
864{"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 },
865{"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 },
866{"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 },
867{"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 },
868{"AND", 1, "11101wwwyyy01100", RR, AND, NONE },
869{"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ },
870{"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ },
871{"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ },
872{"BREAK", 1, "01100??????00101", RR, BREAK, NOARG },
873{"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ },
874{"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ },
875{"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE },
876{"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE },
877{"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD },
878{"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD },
879{"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD },
880{"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD },
881{"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD },
882{"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD },
883{"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO },
884{"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO },
885{"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO },
886{"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO },
887{"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO },
888{"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO },
889{"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL },
890{"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG },
891{"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC },
892{"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG},
893{"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL },
894{"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG},
895{"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED},
896#if 0
897 /* FIXME: Should we handle these ourselves, or should we require an
898 emulation routine? */
899{"EXIT", 1, "1110111100001000", RR, BREAK, EXIT },
900{"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY },
901#endif
902{"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG },
903{"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG },
904{"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK },
905{"JR", 1, "11101xxx00000000", RR, JUMP, NONE },
906{"JRRA", 1, "1110100000100000r", RR, JUMP, NONE },
907{"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND },
908{"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE },
909{"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD },
910{"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD },
911{"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD },
912{"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND },
913{"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD },
914{"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE },
915{"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND },
916{"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND },
917{"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND },
918{"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD },
919{"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT },
920{"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT },
921{"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE },
922{"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE },
923{"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO},
924{"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO },
925{"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD },
926{"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT },
927{"OR", 1, "11101wwwyyy01101", RR, OR, NONE },
928{"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE },
929{"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD },
930{"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD },
931{"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD },
932{"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD },
933{"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL },
934{"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG},
935{"SLT", 1, "11101xxxyyy00010T", RR, SET, LT },
936{"SLTI", 1, "01010xxx88888888T", RI, SET, LT },
937{"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED },
938{"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED },
939{"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC },
940{"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG },
941{"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL },
942{"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG },
943{"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 },
944{"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD },
945{"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD },
063443cf 946{"SWRASP", 1, "01100010VVVVVVVVQs", I8, STORE, WORD },
831f59a2
ILT
947{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
948};
949
950static int bitmap_val PARAMS ((const char *, int, int));
951static void build_mips16_operands PARAMS ((const char *));
952static void build_instruction
953 PARAMS ((int, unsigned int, int, const struct instruction *));
954
8ad57737
JSC
955/*---------------------------------------------------------------------------*/
956
276c2d7d
GRK
957static char*
958name_for_data_len( insn )
959 struct instruction* insn;
960 {
961 if (GETDATASIZEINSN(insn) == BYTE)
962 return "BYTE";
963
964 else if (GETDATASIZEINSN(insn) == HALFWORD)
965 return "HALFWORD";
966
967 else if (GETDATASIZEINSN(insn) == WORD)
968 return "WORD";
969
970 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
971 return "DOUBLEWORD";
972
973 else if (GETDATASIZEINSN(insn) == QUADWORD)
974 return "QUADWORD";
975
976 else
977 return 0;
978 }
979
980static char*
981letter_for_data_len( insn )
982 struct instruction* insn;
983 {
984 if (GETDATASIZEINSN(insn) == BYTE)
985 return "B";
986
987 else if (GETDATASIZEINSN(insn) == HALFWORD)
988 return "H";
989
990 else if (GETDATASIZEINSN(insn) == WORD)
991 return "W";
992
993 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
994 return "D";
995
996 else if (GETDATASIZEINSN(insn) == QUADWORD)
997 return "Q";
998
999 else
1000 return 0;
1001 }
1002
1003static char*
1e851d2c 1004type_for_data_len( insn , is_signed )
276c2d7d 1005 struct instruction* insn;
1e851d2c 1006 int is_signed;
276c2d7d
GRK
1007 {
1008 if (GETDATASIZEINSN(insn) == BYTE)
1e851d2c 1009 return is_signed ? "int" : "unsigned int";
276c2d7d
GRK
1010
1011 else if (GETDATASIZEINSN(insn) == HALFWORD)
1e851d2c 1012 return is_signed ? "int" : "unsigned int";
276c2d7d
GRK
1013
1014 else if (GETDATASIZEINSN(insn) == WORD)
1e851d2c 1015 return is_signed ? "signed64" : "unsigned64";
276c2d7d
GRK
1016
1017 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1e851d2c 1018 return 0;
276c2d7d
GRK
1019
1020 else if (GETDATASIZEINSN(insn) == QUADWORD)
1021 return 0;
1022
1023 else
1024 return 0;
1025 }
8ad57737 1026
276c2d7d
GRK
1027static char*
1028max_for_data_len( insn )
1029 struct instruction* insn;
1030 {
1031 if (GETDATASIZEINSN(insn) == BYTE)
1032 return "127";
1033
1034 else if (GETDATASIZEINSN(insn) == HALFWORD)
1035 return "32767";
1036
1037 else if (GETDATASIZEINSN(insn) == WORD)
1038 return "(int)0x7FFFFFFF";
1039
1040 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1041 return 0;
1042
1043 else if (GETDATASIZEINSN(insn) == QUADWORD)
1044 return 0;
1045
1046 else
1047 return 0;
1048 }
1049
1050static char*
1051min_for_data_len( insn )
1052 struct instruction* insn;
1053 {
1054 if (GETDATASIZEINSN(insn) == BYTE)
1055 return "-128";
1056
1057 else if (GETDATASIZEINSN(insn) == HALFWORD)
1058 return "-32768";
1059
1060 else if (GETDATASIZEINSN(insn) == WORD)
1061 return "(int)0x80000000";
1062
1063 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1064 return 0;
1065
1066 else if (GETDATASIZEINSN(insn) == QUADWORD)
1067 return 0;
1068
1069 else
1070 return 0;
1071 }
1072
1073static char*
1074umax_for_data_len( insn )
1075 struct instruction* insn;
1076 {
1077 if (GETDATASIZEINSN(insn) == BYTE)
1078 return "0xFF";
1079
1080 else if (GETDATASIZEINSN(insn) == HALFWORD)
1081 return "0xFFFF";
1082
1083 else if (GETDATASIZEINSN(insn) == WORD)
1084 return "0xFFFFFFFF";
1085
1086 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1087 return 0;
1088
1089 else if (GETDATASIZEINSN(insn) == QUADWORD)
1090 return 0;
1091
1092 else
1093 return 0;
1094 }
1095
1096static char*
1097bits_for_data_len( insn )
1098 struct instruction* insn;
1099 {
1100 if (GETDATASIZEINSN(insn) == BYTE)
1101 return "8";
1102
1103 else if (GETDATASIZEINSN(insn) == HALFWORD)
1104 return "16";
1105
1106 else if (GETDATASIZEINSN(insn) == WORD)
1107 return "32";
1108
1109 else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
1110 return "64";
1111
1112 else if (GETDATASIZEINSN(insn) == QUADWORD)
1113 return "128";
1114
1115 else
1116 return 0;
1117 }
1118
1119/*---------------------------------------------------------------------------*/
1120
1121
1122void
8ad57737
JSC
1123convert_bitmap(bitmap,onemask,zeromask,dontmask)
1124 char *bitmap;
1125 unsigned int *onemask, *zeromask, *dontmask;
1126{
8ad57737
JSC
1127 int loop; /* current bitmap position */
1128 int lastsp = -1; /* last bitmap field starting position */
1129 int lastoe = -1; /* last bitmap field encoding */
1130
1131 *onemask = 0x00000000;
1132 *zeromask = 0x00000000;
1133 *dontmask = 0x00000000;
1134
1135 if (strlen(bitmap) != 32) {
1136 fprintf(stderr,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap);
1137 exit(3);
1138 }
1139
1140 for (loop = 0; (loop < 32); loop++) {
1141 int oefield ;
1142 for (oefield = 0; (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))); oefield++)
1143 if (bitmap[31 - loop] == opfields[oefield].id)
1144 break;
1145 if (oefield < (sizeof(opfields) / sizeof(struct operand_encoding))) {
1146 if ((lastoe != -1) && (lastoe != oefield))
1147 if ((loop - lastsp) != (opfields[lastoe].flen)) {
8bae0a0c 1148 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
1149 exit(4);
1150 }
1151
1152 switch (bitmap[31 - loop]) {
1153 case '0' : /* fixed value */
1154 *zeromask |= (1 << loop);
1155 lastsp = loop;
1156 lastoe = -1;
1157 break;
1158
1159 case '1' : /* fixed value */
1160 *onemask |= (1 << loop);
1161 lastsp = loop;
1162 lastoe = -1;
1163 break;
1164
1165 case '?' : /* fixed value */
1166 *dontmask |= (1 << loop);
1167 lastsp = loop;
1168 lastoe = -1;
1169 break;
1170
1171 default : /* check character encoding */
1172 {
1173 if (opfields[oefield].fpos != -1) {
1174 /* If flag not set, then check starting position: */
276c2d7d 1175 if (lastoe != oefield) {
8ad57737
JSC
1176 if (loop != opfields[oefield].fpos) {
1177 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);
1178 exit(4);
1179 }
8ad57737
JSC
1180 lastsp = loop;
1181 lastoe = oefield;
1182 }
1183 }
1184 *dontmask |= (1 << loop);
1185 }
1186 break;
1187 }
1188 } else {
1189 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);
1190 exit(4);
1191 }
1192 }
1193
1194 /* NOTE: Since we check for the position and size of fields when
1195 parsing the "bitmap" above, we do *NOT* need to check that invalid
1196 field combinations have been used. */
8ad57737
JSC
1197}
1198
831f59a2
ILT
1199/* Get the value of a 16 bit bitstring for a given shift count and
1200 number of bits. */
1201
1202static int
1203bitmap_val (bitmap, shift, bits)
1204 const char *bitmap;
1205 int shift;
1206 int bits;
1207{
1208 const char *s;
1209 int ret;
1210
1211 ret = 0;
1212 s = bitmap + 16 - shift - bits;
1213 for (; bits > 0; --bits)
1214 {
1215 ret <<= 1;
1216 if (*s == '0')
1217 ;
1218 else if (*s == '1')
1219 ret |= 1;
1220 else
1221 abort ();
1222 ++s;
1223 }
1224
1225 return ret;
1226}
1227
8ad57737
JSC
1228/*---------------------------------------------------------------------------*/
1229
1230static void
276c2d7d
GRK
1231build_operands(doisa,features,insn)
1232 int doisa;
1233 unsigned int features;
1234 instruction* insn;
8ad57737 1235{
276c2d7d
GRK
1236 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1237 int finish_jump_flag = 0;
1238 int check_mult = 0;
1239 int check_condition_code = 0;
1240 int sfield_used = 0;
1241 int gfield_used = 0;
1242 int any_operand = 0;
8ad57737 1243
276c2d7d
GRK
1244 int current_field_id = -1;
1245 int bitpos;
8ad57737 1246
276c2d7d
GRK
1247 for (bitpos=0; bitpos<32; bitpos++) {
1248 if (insn->bitmap[31-bitpos] != current_field_id)
1249 {
1250 int opindex;
8ad57737 1251
276c2d7d 1252 current_field_id = insn->bitmap[31-bitpos];
8ad57737 1253
276c2d7d
GRK
1254 for (opindex = 0; (opindex < (sizeof(opfields) / sizeof(operand_encoding))); opindex++)
1255 if ((opfields[opindex].fpos != -1) && (opfields[opindex].id == insn->bitmap[31-bitpos])) {
8ad57737 1256
276c2d7d 1257 any_operand = 1;
8ad57737 1258
50a2a691 1259 printf(" %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name);
8ad57737 1260
276c2d7d
GRK
1261 if (opfields[opindex].flags & OP_SIGNX)
1262 printf("SIGNEXTEND((%s)",opfields[opindex].type);
8ad57737 1263
276c2d7d
GRK
1264 if (opfields[opindex].flags & OP_GPR)
1265 printf("GPR[");
8ad57737 1266
276c2d7d
GRK
1267 if (opfields[opindex].flags & OP_SHIFT2)
1268 printf("(");
8ad57737 1269
276c2d7d
GRK
1270 printf("((instruction >> %d) & 0x%08X)",opfields[opindex].fpos,((1 << opfields[opindex].flen) - 1));
1271
1272 if (opfields[opindex].flags & OP_SHIFT2)
1273 printf(" << 2)");
1274
1275 if (opfields[opindex].flags & OP_GPR)
1276 printf("]");
1277
1278 if (opfields[opindex].flags & OP_BITS5)
1279 printf("&0x1F");
1280
1281 if (opfields[opindex].flags & OP_SIGNX)
1282 printf(",%d)",(opfields[opindex].flen + ((opfields[opindex].flags & OP_SHIFT2) ? 2 : 0)));
1283
1284 printf(";\n");
1285
1286 if (opfields[opindex].flags & OP_GPR1)
1287 {
1288 printf(" %s %s1 = GPR1[",opfields[opindex].type,opfields[opindex].name);
1289 printf("((instruction >> %d) & 0x%08X)",
1290 opfields[opindex].fpos,
1291 ((1 << opfields[opindex].flen) - 1));
1292 printf("];\n");
1293 }
1294
1295 if (opfields[opindex].id == 'j')
1296 finish_jump_flag = 1;
1297
1298 if (opfields[opindex].id == 'e')
1299 check_mult = 8;
1300
1301 if (opfields[opindex].id == 'w')
1302 check_mult = 4;
1303
1304 if (opfields[opindex].id == 'w')
1305 check_mult = 2;
1306
1307 if (opfields[opindex].id == 'p')
1308 check_condition_code = 1;
1309
1310 if (opfields[opindex].id == 's')
1311 sfield_used = 1;
1312
1313 if (opfields[opindex].id == 'g')
1314 gfield_used = 1;
1315 }
1316 }
1317 }
1318
1319 if ( !any_operand && !(insn->flags & NOARG)) {
1320 fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn->name) ;
1321 exit(5) ;
1322 }
1323
1324 /* Finish constructing the jump address if required: */
1325 if (finish_jump_flag)
1326 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1327
1328 /* Now perform required operand checks: */
1329
1330 /* The following code has been removed, since it seems perfectly
1331 reasonable to have a non-aligned offset that is added to another
1332 non-aligned base to create an aligned address. Some more
1333 information on exactly what the MIPS IV specification requires is
1334 needed before deciding on the best strategy. Experimentation with a
1335 VR4300 suggests that we do not need to raise the warning. */
1336#if 0
1337 /* For MIPS IV (and onwards), certain instruction operand values
1338 will give undefined results. For the simulator we could
1339 generate explicit exceptions (i.e. ReservedInstruction) to
1340 make it easier to spot invalid use. However, for the moment we
1341 just raise a warning. NOTE: This is a different check to the
1342 later decoding, which checks for the final address being
1343 valid. */
1344
1345 if (check_mult != 0 && check_mult != 1) {
1346 printf(" if (instruction & 0x%1X)\n", check_mult);
1347 printf(" {\n");
1348 /* NOTE: If we change this to a SignalException(), we must
1349 ensure that the following opcode processing is not
1350 executed. i.e. the code falls straight out to the simulator
1351 control loop. */
1352 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1353 printf(" }\n");
1354 }
1355#endif
1356
1357 /* The extended condition codes only appeared in ISA IV */
1358 if (check_condition_code && (doisa < 4)) {
1359 printf(" if (condition_code != 0)\n");
1360 printf(" {\n");
1361 printf(" SignalException(ReservedInstruction,instruction);\n");
1362 printf(" }\n");
1363 printf(" else\n");
1364 }
1365
1366 if ((insn->flags & WORD32) && (GETDATASIZEINSN(insn) != WORD)) {
1367 fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1368 exit(1);
1369 }
1370
1371#if 1
1372 /* The R4000 book differs slightly from the MIPS IV ISA
1373 manual. An example is the sign-extension of a 64-bit processor
1374 SUBU operation, and what is meant by an Undefined Result. This
1375 is now provided purely as a warning. After examining a HW
1376 implementation, this is now purely a warning... and the actual
1377 operation is performed, with possibly undefined results. */
1378 if (((insn->flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
1379 /* The compiler should optimise out an OR with zero */
1380 printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
1381 printf(" UndefinedResult();\n") ;
1382 }
1383#else
1384 /* Check that the source is a 32bit value */
1385 if ((insn->flags & WORD32) && proc64) {
1386 /* The compiler should optimise out an OR with zero */
1387 printf(" if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
1388 printf(" UndefinedResult();\n") ;
1389 printf(" else\n") ;
1390 }
1391#endif
1392
1393 return;
8ad57737
JSC
1394}
1395
831f59a2
ILT
1396/* The mips16 operand table. */
1397
1398struct mips16_op
1399{
1400 /* The character which appears in the bitmap string. */
1401 int type;
1402 /* The type of the variable in the simulator. */
1403 const char *vartype;
1404 /* The name of the variable in the simulator. */
1405 const char *name;
1406 /* The number of bits. */
1407 int nbits;
1408 /* The number of bits when extended (zero if can not be extended). */
1409 int extbits;
1410 /* The amount by which the short form is shifted when it is used;
1411 for example, the sw instruction has a shift count of 2. */
1412 int shift;
1413 /* Flags. */
1414 int flags;
1415};
1416
1417/* Flags which appears in the mips16 operand table. */
1418
1419/* Whether this is a mips16 register index. */
1420#define MIPS16_REG16 (0x1)
1421/* Whether this is a register value. */
1422#define MIPS16_REGVAL (0x2)
1423/* Whether this is a swapped mips32 register index (MOV32R) */
1424#define MIPS16_REG32_SWAPPED (0x4)
1425/* Whether this index is also the destination register. */
1426#define MIPS16_DESTREG (0x8)
1427/* Whether the short form is unsigned. */
1428#define MIPS16_UNSP (0x10)
1429/* Whether the extended form is unsigned. */
1430#define MIPS16_EXTU (0x20)
1431/* Implicit stack pointer. */
1432#define MIPS16_SP (0x40)
1433/* Implicit program counter. */
1434#define MIPS16_PC (0x80)
1435/* Implicit $0. */
1436#define MIPS16_ZERO (0x100)
1437/* Implicit $24. */
1438#define MIPS16_TREG (0x200)
1439/* Implicit $31. */
1440#define MIPS16_RA (0x400)
1441/* Jump address. */
1442#define MIPS16_JUMP_ADDR (0x800)
1443/* Branch offset. */
1444#define MIPS16_BRANCH (0x1000)
1445
1446/* The mips16 operand table. */
1447
1448static const struct mips16_op mips16_op_table[] =
1449{
1450 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16 },
1451 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
1452 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG},
1453 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
1454 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG },
1455 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL },
1456 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED },
1457 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR },
1458 { 'e', "int", "ext", 11, 0, 0, 0 },
1459 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
1460 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
1461 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
1462 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
1463 { '4', "int", "op2", 4, 15, 0, 0 },
1464 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP },
1465 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP },
1466 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP },
1467 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP },
1468 { 'j', "int", "op2", 5, 16, 0, 0 },
1469 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP },
1470 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP },
1471 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP },
1472 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP | MIPS16_EXTU },
1473 { 'k', "int", "op2", 8, 16, 0, 0 },
1474 { 'K', "int", "op2", 8, 16, 3, 0 },
1475 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH },
1476 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH },
1477 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP },
1478 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP },
1479 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP },
1480
1481 /* The remaining operands are special operands which encode implied
1482 arguments. These only appear at the end of a bitmap string, and
1483 do not represent actual bits. */
1484 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP | MIPS16_REGVAL },
1485 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP|MIPS16_REGVAL|MIPS16_DESTREG },
1486 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC },
1487 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO },
1488 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO },
1489 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG | MIPS16_REGVAL },
1490 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG },
1491 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
1492 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA },
1493 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
1494
1495 { '\0', NULL, NULL, 0, 0, 0, 0 }
1496};
1497
1498/* Build mips16 operands. */
1499
1500static void
1501build_mips16_operands (bitmap)
1502 const char *bitmap;
1503{
1504 const char *s;
1505 int start = -1;
1506 const struct mips16_op *op = NULL;
1507 const struct mips16_op *ops[3];
1508 int opindex = 0;
1509 int i;
1510
1511 for (s = bitmap; *s != '\0'; s++)
1512 {
1513 if (op != NULL)
1514 {
1515 if (op->type == *s)
1516 continue;
1517
1518 /* Make sure we saw the right number of bits for that
1519 operand. */
1520 if (op->nbits != 0 && (s - bitmap) - op->nbits != start)
1521 abort ();
1522 op = NULL;
1523 }
1524
1525 if (*s == '0' || *s == '1' || *s == '?')
1526 continue;
1527
1528 start = s - bitmap;
1529
1530 for (op = mips16_op_table; op->type != *s; ++op)
1531 if (op->type == '\0')
1532 abort ();
1533
1534 printf (" %s %s = ", op->vartype, op->name);
1535 if (op->nbits != 0)
1536 printf ("(instruction >> %d) & 0x%x",
1537 16 - (s - bitmap) - op->nbits,
1538 (1 << op->nbits) - 1);
1539 else
1540 {
1541 if ((op->flags & MIPS16_SP) != 0)
1542 printf ("29");
1543 else if ((op->flags & MIPS16_PC) != 0)
1544 {
1545 int j;
1546
bd2f6347 1547 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : (have_extendval ? IPC - 2 : IPC)) & ~ (uword64) 1)");
831f59a2
ILT
1548 for (j = 0; j < opindex; j++)
1549 if (ops[j]->shift != 0)
aaff8437 1550 printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
831f59a2
ILT
1551 }
1552 else if ((op->flags & MIPS16_ZERO) != 0)
1553 printf ("0");
1554 else if ((op->flags & MIPS16_TREG) != 0)
1555 printf ("24");
1556 else if ((op->flags & MIPS16_RA) != 0)
1557 printf ("31");
1558 else
1559 abort ();
1560 }
1561 printf (";\n");
1562
1563 if ((op->flags & MIPS16_DESTREG) != 0)
1564 printf (" int destreg;\n");
1565
1566 if (opindex > 2)
1567 abort ();
1568 ops[opindex] = op;
1569 ++opindex;
1570 }
1571
1572 if (op != NULL)
1573 {
1574 /* Make sure we saw the right number of bits for that
1575 operand. */
1576 if (op->nbits != 0 && 16 - op->nbits != start)
1577 abort ();
1578 }
1579
1580 for (i = 0; i < opindex; i++)
1581 {
1582 op = ops[i];
1583 if ((op->flags & MIPS16_REG16) != 0)
1584 {
1585 printf (" if (%s < 2)\n", op->name);
1586 printf (" %s += 16;\n", op->name);
1587 }
1588 if ((op->flags & MIPS16_REG32_SWAPPED) != 0)
1589 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1590 op->name, op->name, op->name);
1591 if ((op->flags & MIPS16_DESTREG) != 0)
1592 printf (" destreg = %s;\n", op->name);
1593 if ((op->flags & MIPS16_REGVAL) != 0)
1594 printf (" %s = GPR[%s];\n", op->name, op->name);
1595
1596 if (op->extbits != 0)
1597 {
1598 printf (" if (have_extendval)\n");
1599 printf (" {\n");
1600 if (op->extbits == 16)
1601 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1602 op->name);
1603 else if (op->extbits == 15)
1604 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1605 op->name);
1606 else if (op->extbits == 6)
1607 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1608 op->name);
1609 else
1610 printf (" %s = (extendval >> 6) & 0x1f;\n",
1611 op->name);
1612 if ((op->flags & MIPS16_EXTU) == 0)
1613 {
1614 printf (" if (%s >= 0x%x)\n",
1615 op->name, 1 << (op->extbits - 1));
1616 printf (" %s -= 0x%x;\n",
1617 op->name, 1 << op->extbits);
1618 }
1619 printf (" have_extendval = 0;\n");
1620 printf (" }\n");
1621 printf (" else\n");
1622 printf (" {\n");
1623 if ((op->flags & MIPS16_UNSP) == 0)
1624 {
1625 printf (" if (%s >= 0x%x)\n",
1626 op->name, 1 << (op->nbits - 1));
1627 printf (" %s -= 0x%x;\n",
1628 op->name, 1 << op->nbits);
1629 }
1630 if (op->shift != 0)
1631 printf (" %s <<= %d;\n", op->name, op->shift);
1632 if (op->type == '<' || op->type == '>'
1633 || op->type == '[' || op->type == ']')
1634 {
1635 printf (" if (%s == 0)\n", op->name);
1636 printf (" %s = 8;\n", op->name);
1637 }
1638 printf (" }\n");
1639 }
1640
1641 if ((op->flags & MIPS16_BRANCH) != 0)
1642 printf (" %s *= 2;\n", op->name);
1643
1644 if ((op->flags & MIPS16_JUMP_ADDR) != 0)
1645 {
1646 printf (" {\n");
1647 printf (" uword64 paddr;\n");
1648 printf (" int uncached;\n");
1649 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1650 printf (" {\n");
1651 printf (" uword64 memval;\n");
1652 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1653 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1654 printf (" unsigned int byte;\n");
1655 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
276c2d7d 1656 printf (" LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
831f59a2
ILT
1657 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1658 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1659 printf (" %s = (((%s & 0x1f) << 23)\n", op->name, op->name);
1660 printf (" | ((%s & 0x3e0) << 13)\n", op->name);
1661 printf (" | (memval << 2));\n");
1662 printf (" if ((instruction & 0x400) == 0)\n");
1663 printf (" %s |= 1;\n", op->name);
1664 printf (" PC += 2;\n");
1665 printf (" }\n");
1666 printf (" }\n");
1667 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op->name);
1668 }
1669 }
1670
1671 /* FIXME: Is this the way to detect an unused extend opcode? */
1672 printf (" if (have_extendval)\n");
1673 printf (" SignalException (ReservedInstruction, instruction);\n");
1674}
1675
e871dd18
JSC
1676/*---------------------------------------------------------------------------*/
1677
1678typedef enum {
1679 s_left,
1680 s_right
1681} e_endshift;
1682
1683static void
1684build_endian_shift(proc64,datalen,endbit,direction,shift)
1685 int proc64;
1686 int datalen;
1687 int endbit;
1688 e_endshift direction;
1689 int shift;
1690{
063443cf 1691 if (datalen == 4) {
e871dd18
JSC
1692 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit,endbit);
1693 printf(" memval %s= %d;\n",direction == s_left ? "<<" : ">>",shift);
1694 printf(" }\n");
1695 }
1696
1697 return;
1698}
1699
8ad57737
JSC
1700/*---------------------------------------------------------------------------*/
1701/* doisa = number of MIPS ISA simulator table is being constructed for.
1702 * proc64 = TRUE if constructing 64bit processor world.
1703 * dofp = boolean, TRUE if FP instructions are to be included.
1704 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1705 */
1706
1707void
1708process_instructions(doarch,features)
1709 unsigned int doarch;
1710 unsigned int features;
1711{
1712 int doisa = (doarch & MASK_ISA);
1713 int limit = (sizeof(MIPS_DECODE) / sizeof(instruction));
1714 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
8ad57737
JSC
1715 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
1716 int dofp = (features & FEATURE_HASFPU);
1717 int fpsingle = (features & FEATURE_FPSINGLE);
8bae0a0c 1718 int maxisa;
8ad57737
JSC
1719 int loop;
1720
1721 if (limit < 1) {
1722 fprintf(stderr,"process_instructions: invalid structure length\n");
1723 exit(1);
1724 }
1725
1726 if (proc64 && (gprlen != 64)) {
1727 fprintf(stderr,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1728 exit(3);
1729 }
1730
8ad57737
JSC
1731 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1732
8bae0a0c
JSC
1733 maxisa = 0;
1734 for (loop = 0; (loop < limit); loop++)
1735 if ((MIPS_DECODE[loop].isa & MASK_ISA) > maxisa)
1736 maxisa = (MIPS_DECODE[loop].isa & MASK_ISA);
1737
1738 if (doisa == 0)
1739 doisa = maxisa;
1740
8ad57737 1741 printf("#if defined(SIM_MANIFESTS)\n");
8bae0a0c 1742 printf("#define MIPSISA (%d)\n",doisa);
8ad57737
JSC
1743 if (proc64)
1744 printf("#define PROCESSOR_64BIT (1 == 1)\n");
c98ec95d
JSC
1745 else
1746 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1747#if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1748 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1749#else
8ad57737 1750 printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
c98ec95d 1751#endif
8bae0a0c 1752 /* The FP registers are the same width as the CPU registers: */
8ad57737 1753 printf("#define GPRLEN (%d)\n",gprlen);
8ad57737
JSC
1754 printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
1755 printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
8bae0a0c 1756 printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
8ad57737
JSC
1757 if (dofp)
1758 printf("#define HASFPU (1 == 1)\n");
1759 if (features & FEATURE_FAST)
1760 printf("#define FASTSIM (1 == 1)\n");
1761 if (features & FEATURE_WARN_STALL)
1762 printf("#define WARN_STALL (1 == 1)\n");
1763 if (features & FEATURE_WARN_LOHI)
1764 printf("#define WARN_LOHI (1 == 1)\n");
1765 if (features & FEATURE_WARN_ZERO)
1766 printf("#define WARN_ZERO (1 == 1)\n");
1767 if (features & FEATURE_WARN_MEM)
1768 printf("#define WARN_MEM (1 == 1)\n");
1769 if (features & FEATURE_WARN_R31)
1770 printf("#define WARN_R31 (1 == 1)\n");
1771 if (features & FEATURE_WARN_RESULT)
1772 printf("#define WARN_RESULT (1 == 1)\n");
1773
1774 printf("#else /* simulator engine */\n");
1775
1776 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1777 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
1778 if (dofp)
1779 printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
1780 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1781
1782 if (proc64) {
1783 printf("#if !defined(PROCESSOR_64BIT)\n");
1784 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1785 printf("#endif\n");
1786 }
1787
1788 printf("/* Actual instruction decoding block */\n");
831f59a2 1789 printf("if ((vaddr & 1) == 0){\n");
8bae0a0c
JSC
1790 {
1791 int limit;
1792 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
1793 limit = (OP_MASK_OP + 1);
276c2d7d
GRK
1794
1795 printf("#ifdef DEBUG\n");
1796 printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
1797 printf("#endif\n");
1798
8bae0a0c
JSC
1799 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1800 limit += (OP_MASK_SPEC + 1);
276c2d7d 1801
8bae0a0c
JSC
1802 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
1803 limit += (OP_MASK_RT + 1);
276c2d7d 1804
8bae0a0c
JSC
1805 printf("else if (num == 0x11) {\n");
1806 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
1807 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
1808 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
1809 printf(" else\n");
1810 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1811 limit += (OP_MASK_SPEC + 1);
276c2d7d 1812
8bae0a0c
JSC
1813 printf(" else\n");
1814 /* To keep this code quick, we just clear out the "to" bit
1815 here. The proper (though slower) code would be to have another
1816 conditional, checking whether this instruction is a branch or
1817 not, before limiting the range to the bottom two bits of the
1818 move operation. */
1819 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
1820 limit += (OP_MASK_COP1SPEC + 1);
276c2d7d 1821
8bae0a0c
JSC
1822 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
1823 limit += (OP_MASK_SPEC + 1);
276c2d7d
GRK
1824
1825 printf("else if (num == 0x1C) {\n");
1826 printf(" int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI);
1827
1828 printf(" if (mmi_func == 0x08) \n");
1829 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1830 limit += (OP_MASK_MMISUB + 1);
1831
1832 printf(" else if (mmi_func == 0x28) \n");
1833 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1834 limit += (OP_MASK_MMISUB + 1);
1835
1836 printf(" else if (mmi_func == 0x09) \n");
1837 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1838 limit += (OP_MASK_MMISUB + 1);
1839
1840 printf(" else if (mmi_func == 0x29) \n");
1841 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
1842 limit += (OP_MASK_MMISUB + 1);
1843
1844 printf(" else \n");
1845 printf(" num = (%d + mmi_func);\n",limit);
1846 limit += (OP_MASK_MMI + 1);
1847
1848 printf("}\n");
1849
8bae0a0c
JSC
1850 printf("/* Total possible switch entries: %d */\n",limit) ;
1851 }
276c2d7d
GRK
1852
1853 printf("#ifdef DEBUG\n");
1854 printf("printf(\"DBG: num = %%d\\n\",num);\n");
1855 printf("#endif\n");
1856
8ad57737
JSC
1857 printf("switch (num)\n") ;
1858 printf("{\n");
1859
a9f7253f 1860 for (loop = 0; (loop < limit); loop++) {
276c2d7d
GRK
1861 /* First check if the insn is in a requested isa# independent set,
1862 then check that the ISA number we are constructing for is
1863 valid, then if the instruction matches any of the
8ad57737
JSC
1864 architecture specific flags. NOTE: We allow a selected ISA of
1865 zero to be used to match all standard instructions. */
528031fd
GRK
1866 unsigned int isa = MIPS_DECODE[loop].isa;
1867 if (((isa & doarch & MASK_ISA_INDEP)
1868 || (((isa & MASK_ISA) <= doisa)
1869 && (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0)))
276c2d7d 1870 && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) {
8ad57737
JSC
1871 unsigned int onemask;
1872 unsigned int zeromask;
1873 unsigned int dontmask;
1874 unsigned int mask;
1875 unsigned int number;
8ad57737 1876
276c2d7d
GRK
1877 convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
1878
1879 if (!(MIPS_DECODE[loop].flags & COPROC)
1880 && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)) {
8ad57737
JSC
1881 fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
1882 exit(4);
1883 }
1884
1885#if defined(DEBUG)
1886 printf("/* DEBUG: onemask 0x%08X */\n",onemask) ;
1887 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask) ;
1888 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask) ;
1889#endif
1890
1891 switch (MIPS_DECODE[loop].mark) {
1892 case NORMAL :
1893 mask = (OP_MASK_OP << OP_SH_OP) ;
1894 number = ((onemask >> OP_SH_OP) & OP_MASK_OP) ;
1895 break ;
1896
1897 case SPECIAL :
1898 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1899 number = ((OP_MASK_OP + 1) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1900 break ;
1901
1902 case REGIMM :
1903 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_RT << OP_SH_RT)) ;
1904 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_RT) & OP_MASK_RT)) ;
1905 break ;
1906
1907 case COP1 :
1908 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
1909 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
1910 break ;
1911
8bae0a0c
JSC
1912 case COP1S :
1913 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_COP1SPEC << OP_SH_COP1SPEC)) ;
1914 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_COP1SPEC) & OP_MASK_COP1SPEC)) ;
1915 break;
1916
8ad57737
JSC
1917 case COP1X :
1918 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_SPEC << OP_SH_SPEC)) ;
8bae0a0c 1919 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
1920 break ;
1921
276c2d7d
GRK
1922 case MMI0 :
1923 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1924 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1925 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1926 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1927 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1928 break ;
1929
1930 case MMI1 :
1931 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1932 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1933 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1934 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1935 + (OP_MASK_MMISUB + 1)
1936 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1937 break ;
1938
1939 case MMI2 :
1940 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1941 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1942 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1943 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1944 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1945 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1946 break ;
1947
1948 case MMI3 :
1949 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
1950 | (OP_MASK_MMISUB << OP_SH_MMISUB));
1951 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1952 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1953 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1954 + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
1955 break ;
1956
1957 case MMINORM :
1958 mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)) ;
1959 number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1)
1960 + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
1961 + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
1962 + (OP_MASK_MMISUB + 1)
1963 + ((onemask >> OP_SH_MMI) & OP_MASK_MMI)) ;
1964 break ;
1965
8ad57737
JSC
1966 default :
1967 fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
1968 exit(5) ;
1969 }
1970
1971 printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
1972
1973#if defined(DEBUG)
1974 printf("/* DEBUG: mask 0x%08X */\n",mask) ;
1975 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
1976#endif
1977
1978 /* Check if there are any other explicit bits in the instruction: */
1979 if ((~mask & (onemask | zeromask)) != 0x00000000) {
1980 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
1981 printf(" {\n") ;
1982 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1983 printf(" }\n") ;
1984 printf(" else\n") ;
1985 }
1986
8ad57737
JSC
1987 printf(" {\n") ;
1988
1989 /* Get hold of the operands */
1990 /* NOTE: If we wanted to make the simulator code smaller, we
1991 * could pull these into a common sequence before we perform
1992 * the instruction decoding. However, this would affect the
1993 * performance since unnecessary field extraction would be
1994 * occurring for certain instructions.
1995 *
1996 * Also we do not perform checking for multiple definitions of a
1997 * particular operand here, since they are caught by the
1998 * compilation of the produced code.
1999 */
276c2d7d 2000 build_operands(doisa, features, &MIPS_DECODE[loop]);
8ad57737
JSC
2001
2002 printf(" {\n") ;
2003
831f59a2 2004 build_instruction (doisa, features, 0, &MIPS_DECODE[loop]);
8ad57737 2005
831f59a2
ILT
2006 printf(" }\n") ;
2007 printf(" }\n") ;
2008 printf(" break ;\n") ;
2009 }
2010 }
8ad57737 2011
831f59a2
ILT
2012 printf("default : /* Unrecognised instruction */\n") ;
2013 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2014 printf(" break ;\n") ;
2015 printf("}\n}\n") ;
8ad57737 2016
831f59a2
ILT
2017 /* Handle mips16 instructions. The switch table looks like this:
2018 0 - 31: I, RI, and RRI instructions by major.
2019 32 - 35: ISHIFT instructions by function + 32
2020 36 - 37: RRI_A instructions by function + 36
2021 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
2022 46 - 49: RRR instructions by function + 46
2023 50 - 81: RR instructions by minor + 50 (except for minor == 0)
2024 82 - 89: I64 and RI64 instructions by funct + 82
2025 90 - 97: jalr (RR minor 0) by y + 90
2026 */
2027 printf ("else {\n");
2028 printf ("static int extendval;\n");
2029 printf ("static int have_extendval;\n");
2030 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
2031 MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
2032 printf ("switch (num)\n{\n");
2033 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
2034 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
2035 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
2036 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
2037 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
2038 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
2039 printf (" break;\n");
2040 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
2041 printf ("default: break;\n}\n");
2042 printf ("switch (num)\n{\n");
2043
2044 for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++)
2045 {
2046 const char *bitmap;
2047 int num;
2048
279cca90
ILT
2049 if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD)
2050 continue;
2051
831f59a2
ILT
2052 bitmap = MIPS16_DECODE[loop].bitmap;
2053 switch (MIPS16_DECODE[loop].mark)
2054 {
2055 case I:
2056 case RI:
2057 case RRI:
2058 num = bitmap_val (bitmap, 11, 5);
2059 break;
2060 case ISHIFT:
2061 num = 32 + bitmap_val (bitmap, 0, 2);
2062 break;
2063 case RRI_A:
2064 num = 36 + bitmap_val (bitmap, 4, 1);
2065 break;
2066 case I8:
2067 case I8_MOV32R:
2068 case I8_MOVR32:
2069 num = 38 + bitmap_val (bitmap, 8, 3);
2070 break;
2071 case RRR:
2072 num = 46 + bitmap_val (bitmap, 0, 2);
2073 break;
2074 case RR:
2075 {
2076 int minor;
2077
2078 minor = bitmap_val (bitmap, 0, 5);
2079 if (minor != 0)
2080 num = 50 + minor;
2081 else
2082 num = 90 + bitmap_val (bitmap, 5, 3);
2083 }
2084 break;
2085 case I64:
2086 case RI64:
2087 num = 82 + bitmap_val (bitmap, 8, 3);
2088 break;
2089 default:
2090 abort ();
2091 }
8ad57737 2092
831f59a2
ILT
2093 printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
2094 bitmap);
8ad57737 2095
831f59a2 2096 printf (" {\n");
8ad57737 2097
831f59a2 2098 build_mips16_operands (bitmap);
8ad57737 2099
831f59a2 2100 printf (" {\n") ;
8ad57737 2101
831f59a2
ILT
2102 /* build_instruction doesn't know about extend. */
2103 if (num != 30)
2104 build_instruction (doisa, features, 1, &MIPS16_DECODE[loop]);
2105 else
2106 {
2107 printf (" extendval = ext;\n");
2108 printf (" have_extendval = 1;\n");
2109 }
8ad57737 2110
831f59a2
ILT
2111 printf (" }\n");
2112 printf (" }\n") ;
2113 printf (" break ;\n") ;
2114 }
8ad57737 2115
831f59a2
ILT
2116 printf ("default : /* Unrecognised instruction */\n") ;
2117 printf (" SignalException(ReservedInstruction,instruction);\n") ;
2118 printf (" break ;\n") ;
2119 printf ("}\n}\n") ;
8ad57737 2120
831f59a2 2121 printf("#endif /* simulator engine */\n");
8ad57737 2122
831f59a2
ILT
2123 return ;
2124}
8ad57737 2125
831f59a2
ILT
2126/* Output the code to execute an instruction, assuming the operands
2127 have already been extracted. */
8ad57737 2128
831f59a2
ILT
2129static void
2130build_instruction (doisa, features, mips16, insn)
2131 int doisa;
2132 unsigned int features;
2133 int mips16;
2134 const struct instruction *insn;
2135{
2136 int gprlen=((features & FEATURE_GP64) ? 64 : 32);
2137 int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
2138 char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
2139
2140 switch (insn->type) {
2141 /* TODO: To make these easier to edit and maintain, they should
2142 actually be provided as source macros (or inline functions)
2143 OUTSIDE this main switch statement. The PPC simulator has a
2144 neater scheme for describing the instruction sequences. */
2145
2146 case ADD:
2147 case SUB:
2148 {
2149 char *signed_basetype = "unknown";
2150 char *unsigned_basetype = "unknown";
2151
2152 switch (GETDATASIZEINSN(insn)) {
2153 case WORD :
2154 signed_basetype = "signed int";
2155 unsigned_basetype = "unsigned int";
2156 break;
2157 case DOUBLEWORD :
2158 signed_basetype = "word64";
2159 unsigned_basetype = "uword64";
2160 break;
2161 default :
2162 fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn));
2163 exit(1);
2164 }
8ad57737 2165
831f59a2
ILT
2166 if ((insn->type) == ADD) {
2167 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
50a2a691 2168 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
831f59a2
ILT
2169 if (insn->flags & OVERFLOW) {
2170 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
2171 printf(" SignalException(IntegerOverflow);\n");
2172 printf(" else\n");
2173 }
2174 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
2175 printf(" GPR[destreg] = (%s)temp;\n",regtype);
2176 else /* only sign-extend when placing 32bit result in 64bit processor */
2177 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
2178 } else { /* SUB */
2179 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype);
50a2a691 2180 printf(" %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
831f59a2
ILT
2181 if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
2182 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
2183 printf(" SignalException(IntegerOverflow);\n");
2184 printf(" else\n");
2185 }
2186 /* UNSIGNED 32bit operations on a 64bit processor should
2187 *STILL* be sign-extended. We have cheated in the
2188 data-structure, by not marking it with UNSIGNED, and not
2189 setting OVERFLOW. */
2190 if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
2191 printf(" GPR[destreg] = (%s)temp;\n",regtype);
2192 else /* only sign-extend when placing 32bit result in 64bit processor */
2193 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
2194 }
2195 }
2196 break ;
8ad57737 2197
831f59a2 2198 case MUL:
276c2d7d
GRK
2199 {
2200 char* pipe = (insn->flags & PIPE1) ? "1" : "";
2201
831f59a2
ILT
2202 if (features & FEATURE_WARN_LOHI) {
2203 printf(" CHECKHILO(\"Multiplication\");\n");
2204 }
2205 printf(" {\n");
2206 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2207 printf(" uword64 mid;\n");
2208 printf(" uword64 midhi;\n");
2209 printf(" uword64 temp;\n");
2210 if ((insn->flags & UNSIGNED) == 0)
2211 {
2212 printf(" int sign = 0;\n");
2213 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
2214 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
2215 }
276c2d7d
GRK
2216 printf(" LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe);
2217 printf(" HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe);
831f59a2
ILT
2218 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
2219 printf(" midhi = SET64HI(WORD64LO(mid));\n");
276c2d7d
GRK
2220 printf(" temp = (LO%s + midhi);\n",pipe);
2221 printf(" if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe);
2222 printf(" HI%s += 1;\n",pipe);
2223 printf(" HI%s += WORD64HI(mid);\n",pipe);
831f59a2
ILT
2224 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
2225 printf(" midhi = SET64HI(WORD64LO(mid));\n");
276c2d7d
GRK
2226 printf(" LO%s = (temp + midhi);\n",pipe);
2227 printf(" if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe,pipe);
2228 printf(" HI%s += 1;\n",pipe);
2229 printf(" HI%s += WORD64HI(mid);\n",pipe);
831f59a2 2230 if ((insn->flags & UNSIGNED) == 0)
276c2d7d 2231 printf(" if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe,pipe,pipe,pipe,pipe);
831f59a2
ILT
2232 } else {
2233 if (insn->flags & UNSIGNED)
2234 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
2235 else
deffd638 2236 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
276c2d7d
GRK
2237 printf(" LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe,regtype);
2238 printf(" HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe,regtype);
831f59a2 2239 }
276c2d7d
GRK
2240 if (insn->flags & OP3)
2241 {
2242 printf(" if ( destreg != 0 )\n");
2243 printf(" GPR[destreg] = LO%s;\n",pipe);
2244 }
831f59a2
ILT
2245 printf(" }\n");
2246 break ;
276c2d7d 2247 }
831f59a2
ILT
2248 case DIV:
2249 {
2250 int boolU = (insn->flags & UNSIGNED);
d654ba0a 2251 char* pipe = (insn->flags & PIPE1) ? "1" : "";
8ad57737 2252
831f59a2 2253 if (features & FEATURE_WARN_LOHI) {
d654ba0a 2254 printf(" CHECKHILO(\"Division\");\n");
831f59a2
ILT
2255 }
2256 printf(" {\n");
d654ba0a 2257
831f59a2 2258 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
d654ba0a
GRK
2259 printf(" %sword64 d1 = op1;\n", (boolU ? "u" : ""));
2260 printf(" %sword64 d2 = op2;\n", (boolU ? "u" : ""));
2261 printf(" if (d2 == 0)\n");
2262 printf(" {\n");
2263 printf(" LO%s = 0x8000000000000000LL;\n", pipe);
2264 printf(" HI%s = 0;\n", pipe);
2265 printf(" }\n");
2266 printf(" else if (d2 == -1 && d1 == 0x8000000000000000LL)\n");
2267 printf(" {\n");
2268 printf(" LO%s = 0x8000000000000000LL;\n", pipe);
2269 printf(" HI%s = 0;\n", pipe);
2270 printf(" }\n");
2271 printf(" else\n");
2272 printf(" {\n");
2273 printf(" LO%s = (d1 / d2);\n", pipe);
2274 printf(" HI%s = (d1 %% d2);\n", pipe);
2275 printf(" }\n");
831f59a2 2276 } else {
d654ba0a
GRK
2277 printf(" %sint d1 = op1;\n", (boolU ? "unsigned " : ""));
2278 printf(" %sint d2 = op2;\n", (boolU ? "unsigned " : ""));
2279 printf(" if (d2 == 0)\n");
2280 printf(" {\n");
2281 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
2282 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe);
2283 printf(" }\n");
2284 printf(" else if (d2 == -1 && d1 == 0x80000000)\n");
2285 printf(" {\n");
2286 printf(" LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
2287 printf(" HI%s = SIGNEXTEND(0,32);\n", pipe);
2288 printf(" }\n");
2289 printf(" else\n");
2290 printf(" {\n");
2291 printf(" LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe);
2292 printf(" HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe);
2293 printf(" }\n");
831f59a2
ILT
2294 }
2295 printf(" }\n");
2296 }
d654ba0a 2297 break ;
831f59a2
ILT
2298
2299 case SHIFT:
2300 {
2301 int datalen = GETDATASIZEINSN(insn);
2302 int bits = ((datalen == WORD) ? 32 : 64);
2303 char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
2304
2305 /* Check that the specified SHIFT is valid: */
2306 if ((datalen == BYTE) || (datalen == HALFWORD)) {
2307 fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn->name);
2308 exit(9);
2309 }
2310 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
2311 fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn->name);
2312 exit(9);
2313 }
2314 if (!(insn->flags & LEFT) && !(insn->flags & RIGHT)) {
2315 fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn->name);
2316 exit(9);
2317 }
2318 if ((insn->flags & LOGICAL) && (insn->flags & ARITHMETIC)) {
2319 fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn->name);
2320 exit(9);
2321 }
2322 if (!(insn->flags & LOGICAL) && !(insn->flags & ARITHMETIC)) {
2323 fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn->name);
2324 exit(9);
2325 }
2326 if ((insn->flags & LEFT) && (insn->flags & ARITHMETIC)) {
2327 fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",insn->name);
2328 exit(9);
2329 }
8ad57737 2330
39bf0ef4
MA
2331 /* Work around an MSC code generation bug by precomputing a value
2332 * with the sign bit set. */
2333 if (insn->flags & ARITHMETIC)
2334 printf(" %s highbit = (%s)1 << %d;\n", ltype, ltype, bits - 1);
2335
831f59a2
ILT
2336 /* If register specified shift, then extract the relevant shift amount: */
2337 if (insn->flags & REG)
2338 printf(" op1 &= 0x%02X;\n",(bits - 1));
2339
2340 /* If HI32 specified, then shift range is 32..63 */
2341 if (insn->flags & HI32)
2342 printf(" op1 |= (1 << 5);\n");
2343
2344 /* We do not need to perform pre-masking with 0xFFFFFFFF when
2345 dealing with 32bit shift lefts, since the sign-extension
2346 code will replace any remaining hi-bits: */
2347 if (insn->flags & LEFT)
2348 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
2349 else
2350 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
2351
2352 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
2353 don't do this if op1 is zero, since it is not needed and
2354 since that would cause an undefined shift of the number of
2355 bits in the type. */
2356 if (insn->flags & ARITHMETIC)
39bf0ef4 2357 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,bits);
831f59a2
ILT
2358
2359 /* Ensure WORD values are sign-extended into 64bit registers */
2360 if ((bits == 32) && (gprlen == 64))
2361 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
2362 }
2363 break ;
2364
2365 case MOVE:
2366 if (insn->flags & (HI | LO)) {
2367 char *regname = ((insn->flags & LO) ? "LO" : "HI");
276c2d7d 2368 int pipe1 = (insn->flags & PIPE1);
831f59a2 2369 if (insn->flags & LEFT)
276c2d7d 2370 printf(" GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : ""));
831f59a2
ILT
2371 else {
2372 if (features & FEATURE_WARN_LOHI) {
276c2d7d 2373 printf(" if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : ""));
831f59a2
ILT
2374 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname);
2375 }
276c2d7d 2376 printf(" %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
831f59a2
ILT
2377 }
2378 if (features & FEATURE_WARN_LOHI)
276c2d7d 2379 printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : ""));
831f59a2
ILT
2380 } else
2381 if (insn->flags & SHIFT16)
2382 printf(" GPR[destreg] = (op2 << 16);\n");
2383 else {
2384 /* perform conditional move */
2385 if (!(insn->flags & EQ)) {
2386 fprintf(stderr,"Standard conditional %s does not have the equality flag\n",insn->name);
2387 exit(8);
2388 }
2389 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
2390 printf(" GPR[destreg] = op1;\n");
2391 }
2392 break ;
2393
2394 case SYNC:
2395 printf(" SyncOperation(op1);\n");
2396 break ;
2397
2398 case SYSCALL:
2399 printf(" SignalException(SystemCall,instruction);\n");
2400 break ;
2401
2402 case BREAK:
2403 printf(" SignalException(BreakPoint,instruction);\n");
2404 break ;
2405
2406 case TRAP:
2407 {
2408 int boolNOT = (insn->flags & NOT);
2409 int boolEQ = (insn->flags & EQ);
2410 int boolGT = (insn->flags & GT);
2411 int boolLT = (insn->flags & LT);
2412 int boolU = (insn->flags & UNSIGNED);
2413
2414 if (boolGT && boolLT) {
2415 fprintf(stderr,"GT and LT specified for \"%s\"\n",insn->name);
2416 exit(8);
2417 }
8ad57737 2418
831f59a2
ILT
2419 if (boolNOT && (boolGT || boolLT)) {
2420 fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",insn->name);
2421 exit(8);
2422 }
8ad57737 2423
831f59a2
ILT
2424 printf(" if ((%sword64)op1 ",(boolU ? "u" : ""));
2425 printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
2426 printf(" (%sword64)op2)\n",(boolU ? "u" : ""));
2427 printf(" SignalException(Trap,instruction);\n");
2428 }
2429 break ;
8ad57737 2430
831f59a2
ILT
2431 case SET:
2432 {
2433 int boolU = (insn->flags & UNSIGNED);
8ad57737 2434
831f59a2
ILT
2435 if (!(insn->flags & LT)) {
2436 fprintf(stderr,"Set instruction without LT specified \"%s\"\n",insn->name);
2437 exit(8);
2438 }
8ad57737 2439
831f59a2
ILT
2440 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
2441 printf(" GPR[destreg] = 1;\n");
2442 printf(" else\n");
2443 printf(" GPR[destreg] = 0;\n");
2444 }
2445 break ;
2446
2447 case AND:
2448 printf(" GPR[destreg] = (op1 & op2);\n");
2449 break ;
2450
2451 case OR:
deffd638
ILT
2452 /* The default mips16 nop instruction does an or to register
2453 zero; catch that case, so that we don't get useless warnings
2454 from the simulator. */
2455 if (mips16)
2456 printf (" if (destreg != 0)\n");
831f59a2
ILT
2457 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn->flags & NOT) ? "~" : ""));
2458 break ;
2459
2460 case XOR:
2461 printf(" GPR[destreg] = (op1 ^ op2);\n");
2462 break ;
2463
2464 case DECODE:
2465 printf(" decode_coproc(instruction);\n");
2466 break ;
2467
2468 case CACHE:
2469 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
2470 /* The virtual address is translated to a physical address using the TLB */
2471 /* The hint specifies a cache operation for that address */
2472 printf(" uword64 vaddr = (op1 + offset);\n");
2473 printf(" uword64 paddr;\n");
2474 printf(" int uncached;\n");
2475 /* NOTE: We are assuming that the AddressTranslation is a load: */
2476 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2477 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
2478 break;
2479
2480 case MADD16: /* VR4100 specific multiply-add instructions */
2481 /* Some of this code is shared with the standard multiply
2482 routines, so an effort should be made to merge where
2483 possible. */
2484 if (features & FEATURE_WARN_LOHI) {
2485 printf(" CHECKHILO(\"Multiply-Add\");\n");
2486 }
2487 if (features & FEATURE_WARN_RESULT) {
2488 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
2489 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
2490 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
2491 }
2492 printf(" {\n");
2493 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
2494 if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
2495 printf(" LO = LO + temp;\n");
2496 } else { /* WORD */
2497 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
2498 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
2499 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
2500 }
2501 printf(" }\n");
2502 break;
2503
2504 case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
2505 if (doisa < 4) {
2506 printf(" if (CoProcPresent(3))\n");
2507 printf(" SignalException(CoProcessorUnusable);\n");
2508 printf(" else\n");
2509 }
2510 printf(" SignalException(ReservedInstruction,instruction);\n");
2511 break ;
2512
2513 case JUMP:
2514 if (insn->flags & LINK) {
2515 if (!(insn->flags & REG))
2516 printf(" int destreg = 31;\n");
2517 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
2518 mips16 ? 2 : 4, mips16 ? 2 : 4);
2519 }
8ad57737 2520
831f59a2
ILT
2521 if (insn->flags & NOT)
2522 printf(" op1 ^= 1;\n");
8ad57737 2523
6429b296
JW
2524 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
2525 printf(" so we just truncate it to 32 bits here. */\n");
2526 printf(" op1 = WORD64LO(op1);\n");
831f59a2
ILT
2527 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
2528 printf(" DSPC = op1;\n");
aaff8437
ILT
2529 if (insn->flags & LINK)
2530 printf(" JALDELAYSLOT();\n");
2531 else
2532 printf(" DELAYSLOT();\n");
831f59a2 2533 break ;
8ad57737 2534
831f59a2
ILT
2535 case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
2536 if (insn->flags & FP) {
2537 if (doisa < 4) {
2538 printf(" if (condition_code != 0)\n");
2539 printf(" SignalException(ReservedInstruction,instruction);\n");
2540 printf(" else {\n");
2541 }
2542 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
2543 printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
2544 } else {
2545 if ((insn->flags & NOT) && !(insn->flags & EQ)) {
2546 fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",insn->name);
2547 exit(7);
2548 }
2549 if ((insn->flags & NOT) && (insn->flags & (GT | LT))) {
2550 fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",insn->name);
2551 exit(7);
2552 }
2553 /* GT LT */
2554 if (insn->flags & GT)
2555 printf(" int condition = (op1 >%s 0);\n",((insn->flags & EQ) ? "=" : ""));
2556 else
2557 if (insn->flags & LT)
2558 printf(" int condition = (op1 <%s 0);\n",((insn->flags & EQ) ? "=" : ""));
2559 else
2560 if (insn->flags & EQ)
2561 printf(" int condition = (op1 %c= op2);\n",((insn->flags & NOT) ? '!' : '='));
2562 }
8ad57737 2563
831f59a2
ILT
2564 if (insn->flags & LINK) {
2565 if (features & FEATURE_WARN_R31) {
2566 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS);
2567 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
2568 }
2569 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
2570 }
8ad57737 2571
831f59a2
ILT
2572 if (! mips16) {
2573 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
2574 printf(" if (condition) {\n");
2575 printf(" DSPC = (PC + offset);\n");
2576 printf(" DELAYSLOT();\n");
2577 printf(" }\n");
2578 } else {
2579 /* No delayed slots for mips16 branches. */
2580 printf(" if (condition)\n");
2581 printf(" PC = PC + offset;\n");
2582 }
2583 if ((insn->flags & FP) && (doisa != 1)) {
2584 printf(" else if (likely) {\n");
2585 printf(" NULLIFY();\n");
2586 printf(" }\n");
2587 } else if (insn->flags & LIKELY) {
2588 printf(" else\n");
2589 printf(" NULLIFY();\n");
2590 }
2591 if ((insn->flags & FP) && (doisa < 4))
2592 printf(" }\n");
2593 break ;
2594
2595 case PREFETCH: /* The beginning is shared with normal load operations */
2596 case LOAD:
2597 case STORE:
2598 {
2599 int isload = ((insn->type == LOAD) || (insn->type == PREFETCH));
2600 int datalen;
2601 char *accesslength = "<UNKNOWN>";
2602
2603 switch (GETDATASIZEINSN(insn)) {
2604 case BYTE :
2605 datalen = 1;
2606 accesslength = "AccessLength_BYTE";
2607 break ;
2608
2609 case HALFWORD :
2610 datalen = 2;
2611 accesslength = "AccessLength_HALFWORD";
2612 break ;
2613
2614 case WORD :
2615 datalen = 4;
2616 accesslength = "AccessLength_WORD";
2617 break ;
2618
2619 case DOUBLEWORD :
2620 datalen = 8;
2621 accesslength = "AccessLength_DOUBLEWORD";
2622 break ;
276c2d7d
GRK
2623
2624 case QUADWORD :
2625 datalen = 16;
2626 accesslength = "AccessLength_QUADWORD";
2627 break ;
831f59a2 2628 }
8ad57737 2629
831f59a2
ILT
2630 if (insn->flags & REG)
2631 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
2632 else
2633 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
2634 printf(" uword64 paddr;\n");
2635 printf(" int uncached;\n");
2636
2637 /* The following check should only occur on normal (non-shifted) memory loads */
2638 if ((datalen != 1) && !(insn->flags & (LEFT | RIGHT))) {
2639 printf(" if ((vaddr & %d) != 0)\n",(datalen - 1));
2640 printf(" SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
2641 printf(" else\n") ;
2642 }
2643
2644 printf(" {\n");
2645 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
2646
2647 if (insn->type == PREFETCH)
2648 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
2649 else {
2650 printf(" {\n");
50a2a691
AC
2651 printf(" uword64 memval = 0;\n");
2652 printf(" uword64 memval1 = 0;\n");
831f59a2
ILT
2653
2654 if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
2655 fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
2656 exit(6);
2657 }
8ad57737 2658
831f59a2
ILT
2659 if (insn->flags & (LEFT | RIGHT)) {
2660 if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
2661 fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn->name);
2662 exit(4);
2663 }
2664
2665 switch (datalen) {
2666 case 8:
2667 if (!proc64) {
2668 fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
2669 exit(4);
2670 }
2671 /* fall through to... */
2672 case 4:
2673 {
2674 printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
2675 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2676 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2677 printf(" int byte;\n");
2678 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2679 printf(" byte = ((vaddr & mask) ^ bigend);\n");
276c2d7d 2680 printf(" if (%s!ByteSwapMem)\n",((insn->flags & LEFT) ? "!" : ""));
831f59a2
ILT
2681 printf(" paddr &= ~mask;\n");
2682
2683 if (isload) {
2684 if (insn->flags & LEFT)
276c2d7d
GRK
2685 {
2686 printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2687 }
831f59a2 2688 else
276c2d7d
GRK
2689 {
2690 printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
2691 }
831f59a2
ILT
2692 }
2693
2694 if (insn->flags & LEFT) {
2695 if (isload) {
2696 /* For WORD transfers work out if the value will
2697 be in the top or bottom of the DOUBLEWORD
2698 returned: */
e871dd18 2699#if 1
831f59a2 2700 build_endian_shift(proc64,datalen,2,s_right,32);
e871dd18 2701#else
831f59a2
ILT
2702 if (proc64 && (datalen == 4)) {
2703 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2704 printf(" memval >>= 32;\n");
2705 printf(" }\n");
2706 }
e871dd18 2707#endif
831f59a2
ILT
2708 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
2709 if (proc64 && (datalen == 4))
2710 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2711 } else { /* store */
2712 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
e871dd18 2713#if 1
831f59a2 2714 build_endian_shift(proc64,datalen,2,s_left,32);
e871dd18 2715#else
831f59a2
ILT
2716 /* TODO: This is duplicated in the LOAD code
2717 above - and the RIGHT LOAD and STORE code
2718 below. It should be merged if possible. */
2719 if (proc64 && (datalen == 4)) {
2720 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2721 printf(" memval <<= 32;\n");
2722 printf(" }\n");
2723 }
e871dd18 2724#endif
276c2d7d 2725 printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
831f59a2
ILT
2726 }
2727 } else { /* RIGHT */
2728 if (isload) {
e871dd18 2729#if 1
831f59a2 2730 build_endian_shift(proc64,datalen,2,s_right,32);
e871dd18 2731#else
831f59a2
ILT
2732 if (proc64 && (datalen == 4)) {
2733 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2734 printf(" memval >>= 32;\n");
2735 printf(" }\n");
2736 }
e871dd18 2737#endif
831f59a2
ILT
2738 printf(" {\n");
2739 printf(" uword64 srcmask;\n");
2740 /* All of this extra code is just a bodge
2741 required because some hosts don't allow
2742 ((v) << 64). The SPARC just leaves the (v)
2743 value un-touched. */
2744 printf(" if (byte == 0)\n");
2745 printf(" srcmask = 0;\n");
2746 printf(" else\n");
2747 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
2748 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2749 printf(" }\n");
2750 if (proc64 && (datalen == 4))
2751 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2752 } else { /* store */
063443cf 2753 printf(" memval = ((uword64) op2 << (byte * 8));\n");
831f59a2 2754 build_endian_shift(proc64,datalen,2,s_left,32);
276c2d7d 2755 printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
831f59a2
ILT
2756 }
2757 }
2758 }
2759 break;
2760
2761 default:
2762 fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
2763 exit(6);
2764 }
2765 } else { /* normal memory transfer */
2766 if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
2767 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
2768 exit(4);
2769 /* TODO: The R4000 documentation states that a LWU
2770 instruction executed when in a 32bit processor mode
2771 should cause a ReservedInstruction exception. This
2772 will mean adding a run-time check into the code
2773 sequence. */
2774 }
2775
2776 if (isload) {
c98ec95d 2777#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2778 printf(" uword64 mask = 0x7;\n");
c98ec95d 2779#else
831f59a2 2780 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2781#endif
831f59a2 2782 printf(" unsigned int shift = %d;\n",(datalen >> 1));
50a2a691
AC
2783 printf(" unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
2784 printf(" unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
2785 printf(" unsigned int byte UNUSED;\n");
8ad57737 2786
c98ec95d 2787/* TODO: This should really also check for 32bit world performing 32bit access */
276c2d7d 2788 if (datalen < 8) /* not for DOUBLEWORD or QUADWORD*/
831f59a2
ILT
2789 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2790
276c2d7d
GRK
2791 printf(" LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
2792
831f59a2
ILT
2793 /* The following will only make sense if the
2794 "LoadMemory" above returns a DOUBLEWORD entity */
276c2d7d 2795 if (datalen < 8) { /* not for DOUBLEWORD or QUADWORD*/
831f59a2
ILT
2796 int valmask;
2797 switch (datalen) {
2798 case 1:
2799 valmask = 0xFF;
2800 break;
2801
2802 case 2:
2803 valmask = 0xFFFF;
2804 break;
2805
2806 case 4:
2807 valmask = 0xFFFFFFFF;
2808 break;
2809
2810 default:
2811 fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,insn->name);
2812 exit(4);
2813 }
2814 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2815 /* NOTE: The R4000 user manual has the COP_LW
2816 occuring in the same cycle as the rest of the
2817 instruction, yet the MIPS IV shows the operation
2818 happening on the next cycle. To keep the simulator
2819 simple, this code follows the R4000
2820 manual. Experimentation with a silicon
2821 implementation will be needed to ascertain the
2822 correct operation. */
2823 if (insn->flags & COPROC)
2824 printf(" COP_LW(%s,destreg,(unsigned int)",
2825 ((insn->flags & REG)
2826 ? "1"
2827 : "((instruction >> 26) & 0x3)"));
2828 else
2829 printf(" GPR[destreg] = (");
2830
2831 if (insn->flags & SIGNEXTEND)
2832 printf("SIGNEXTEND(");
2833 printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
2834 if (insn->flags & SIGNEXTEND)
2835 printf(",%d)",(datalen * 8));
2836 printf(");\n");
2837 } else {
2838 if (insn->flags & COPROC)
2839 printf(" COP_LD(%s,destreg,memval);;\n",
2840 ((insn->flags & REG)
2841 ? "1"
2842 : "((instruction >> 26) & 0x3)"));
2843 else
276c2d7d
GRK
2844 {
2845 printf(" GPR[destreg] = memval;\n");
2846 if (datalen > 8)
2847 printf(" GPR1[destreg] = memval1;\n");
2848 }
831f59a2
ILT
2849 }
2850 } else { /* store operation */
2851 if ((datalen == 1) || (datalen == 2)) {
2852 /* SH and SB */
c98ec95d 2853#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2854 printf(" uword64 mask = 0x7;\n");
c98ec95d 2855#else
831f59a2 2856 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2857#endif
831f59a2
ILT
2858 printf(" unsigned int shift = %d;\n",(datalen >> 1));
2859 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2860 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2861 printf(" unsigned int byte;\n");
2862
2863 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2864 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
063443cf 2865 printf(" memval = ((uword64) op2 << (8 * byte));\n");
831f59a2 2866 } else
063443cf 2867 if (datalen == 4) { /* SC and SW */
c98ec95d 2868#if 1 /* see the comments attached to LOADDRMASK above */
831f59a2 2869 printf(" uword64 mask = 0x7;\n");
c98ec95d 2870#else
831f59a2 2871 printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
c98ec95d 2872#endif
831f59a2
ILT
2873 printf(" unsigned int byte;\n");
2874 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2875 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2876 if (insn->flags & COPROC)
2877 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2878 ((insn->flags & REG)
2879 ? "1"
2880 : "((instruction >> 26) & 0x3)"),
2881 ((insn->flags & FP) ? "fs" : "destreg"));
2882 else
063443cf 2883 printf(" memval = ((uword64) op2 << (8 * byte));\n");
276c2d7d 2884 } else if (datalen <= 8) { /* SD and SCD */
063443cf
ILT
2885 if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
2886 fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
2887 exit(4);
2888 }
831f59a2 2889 if (insn->flags & COPROC)
063443cf 2890 printf(" memval = (uword64)COP_SD(%s,%s);\n",
831f59a2
ILT
2891 ((insn->flags & REG)
2892 ? "1"
2893 : "((instruction >> 26) & 0x3)"),
2894 ((insn->flags & FP) ? "fs" : "destreg"));
2895 else
2896 printf(" memval = op2;\n");
276c2d7d
GRK
2897 } else { /* wider than 8 */
2898 if (insn->flags & COPROC) {
2899 fprintf(stderr,"COPROC not available for 128 bit operations \"%s\"\n",insn->name);
2900 exit(4);
2901 }
2902 printf(" memval = rt_reg;\n");
2903 printf(" memval1 = rt_reg1;\n");
831f59a2
ILT
2904 }
2905
2906 if (insn->flags & ATOMIC)
2907 printf(" if (LLBIT)\n");
2908
2909 printf(" {\n");
276c2d7d 2910 printf(" StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
831f59a2
ILT
2911 printf(" }\n");
2912 }
2913
2914 if (insn->flags & ATOMIC) {
2915 if ((datalen != 4) && (datalen != 8)) {
2916 fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn->name);
2917 exit(4);
2918 } else
2919 if (isload)
2920 printf(" LLBIT = 1;\n");
2921 else {
2922 /* The documentation states that:
2923
2924 SC *WILL* fail if coherent store into the same
2925 block occurs, or if an exception occurs between
2926 the LL and SC instructions.
2927
2928 SC *MAY* fail if a load, store or prefetch is
2929 executed on the processor (VR4300 doesn't seem
2930 to), or if the instructions between the LL and
2931 SC are not in a 2048byte contiguous VM range.
2932
2933 SC *MUST* have been preceded by an LL
2934 (i.e. LLBIT will be set), and it must use the
2935 same Vaddr, Paddr and cache-coherence algorithm
2936 as the LL (which means we should store this
2937 information from the load-conditional).
2938 */
2939 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
2940 }
2941 }
2942 }
2943 printf(" }\n");
8ad57737 2944 }
831f59a2
ILT
2945 printf(" }\n");
2946 }
2947 break ;
2948
2949 case FPPREFX:
2950 /* This code could be merged with the PREFIX generation above: */
2951 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2952 printf(" uword64 paddr;\n");
2953 printf(" int uncached;\n");
2954 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2955 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2956 break ;
2957
2958 case FPMOVEC:
2959 if (insn->flags & CONTROL) {
2960 /* The following "magic" of interpreting the FP
2961 control-register number would not be needed if we were not
2962 trying to match our internal register numbers with those
2963 used by GDB. */
2964 printf(" if (to) {\n");
2965 if (doisa < 4) {
2966 printf(" if (fs == 0) {\n");
2967 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2968 printf(" } else if (fs == 31) {\n");
2969 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2970 printf(" } /* else NOP */\n");
2971 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2972 } else {
2973 printf(" if (fs == 0) {\n");
2974 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2975 printf(" } else if (fs == 31) {\n");
2976 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2977 printf(" } /* else NOP */\n");
2978 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2979 }
2980 printf(" } else { /* control from */\n");
2981 if (doisa < 4) {
2982 printf(" if (fs == 0) {\n");
2983 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2984 printf(" } else if (fs == 31) {\n");
2985 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2986 printf(" } /* else NOP */\n");
2987 } else {
2988 printf(" if (fs == 0) {\n");
2989 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2990 printf(" } else if (fs == 31) {\n");
2991 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2992 printf(" } /* else NOP */\n");
2993 }
2994 printf(" }\n");
2995 } else {
2996 printf(" if (to) {\n");
2997 if (GETDATASIZEINSN(insn) == WORD) {
2998 if (doisa < 4) {
2999 printf(" if (SizeFGR() == 64) {\n");
3000 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
3001 printf(" } else { \n");
3002 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3003 printf(" }\n");
3004 } else {
3005 printf(" if (SizeFGR() == 64)\n");
3006 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
3007 printf(" else\n");
3008 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3009 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3010 }
3011 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
3012 if (doisa < 4) {
3013 printf(" if (SizeFGR() == 64) {\n");
3014 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
3015 printf(" } else\n");
3016 printf(" if ((fs & 0x1) == 0)\n");
3017 printf(" {\n");
3018 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
3019 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
3020 printf(" }\n");
3021 if (features & FEATURE_WARN_RESULT) {
3022 printf(" else\n");
3023 printf(" UndefinedResult();\n");
3024 }
3025 } else {
3026 printf(" if (SizeFGR() == 64) {\n");
3027 printf(" FGR[fs] = GPR[ft];\n");
3028 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3029 printf(" } else\n");
3030 printf(" if ((fs & 0x1) == 0)\n");
3031 printf(" {\n");
3032 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
3033 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
3034 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
3035 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
3036 printf(" }\n");
3037 if (features & FEATURE_WARN_RESULT) {
3038 printf(" else\n");
3039 printf(" UndefinedResult();\n");
3040 }
3041 }
3042 } else {
3043 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
3044 exit(1);
3045 }
3046 printf(" } else {\n");
3047 if (GETDATASIZEINSN(insn) == WORD) {
3048 if (doisa < 4) /* write-back occurs in next cycle */
3049 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
3050 else /* in this cycle */
3051 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
3052 } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
3053 if (doisa < 4) {
3054 printf(" if (SizeFGR() == 64) {\n");
3055 printf(" PENDING_FILL(ft,FGR[fs]);\n");
3056 printf(" } else\n");
3057 printf(" if ((fs & 0x1) == 0) {\n");
3058 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
3059 printf(" } else {\n");
3060 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3061 if (features & FEATURE_WARN_RESULT)
3062 printf(" UndefinedResult();\n");
3063 printf(" }\n");
3064 } else {
3065 printf(" if (SizeFGR() == 64)\n");
3066 printf(" GPR[ft] = FGR[fs];\n");
3067 printf(" else\n");
3068 printf(" if ((fs & 0x1) == 0)\n");
3069 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
3070 printf(" else {\n");
3071 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
3072 if (features & FEATURE_WARN_RESULT)
3073 printf(" UndefinedResult();\n");
3074 printf(" }\n");
3075 }
3076 } else {
3077 fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
3078 exit(1);
3079 }
3080 printf(" }\n");
3081 }
3082 break ;
3083
3084 case FPMOVE:
3085 if (insn->flags & CONDITIONAL) {
3086 if (insn->flags & INTEGER) { /* moving GPR - testing FGR */
3087 printf(" if (GETFCC(condition_code) == boolean)\n");
3088 printf(" GPR[destreg] = op1;\n");
3089 } else {
3090 if (insn->flags & EQ) /* moving FGR - testing GPR */
3091 printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
3092 else
3093 printf(" if (GETFCC(condition_code) == boolean)\n");
3094 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3095 printf(" else\n");
3096 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
3097 }
3098 } else { /* simple MOVE */
3099 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
3100 }
3101 break ;
3102
3103 case FPNEG:
3104 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3105 printf(" SignalException(ReservedInstruction,instruction);\n");
3106 printf(" else\n");
3107 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
3108 break ;
3109
3110 case FPABS:
3111 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3112 printf(" SignalException(ReservedInstruction,instruction);\n");
3113 printf(" else\n");
3114 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
3115 break ;
3116
3117 case FPDIV:
3118 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3119 printf(" SignalException(ReservedInstruction,instruction);\n");
3120 printf(" else\n");
3121 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3122 break ;
3123
3124 case FPMUL:
3125 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3126 printf(" SignalException(ReservedInstruction,instruction);\n");
3127 printf(" else\n");
3128 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3129 break ;
3130
3131 case FPRECIP:
3132 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3133 printf(" SignalException(ReservedInstruction,instruction);\n");
3134 printf(" else\n");
3135 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
3136 break ;
3137
3138 case FPSQRT:
3139 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3140 printf(" SignalException(ReservedInstruction,instruction);\n");
3141 printf(" else\n");
3142 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn->flags & RECIP) ? "Recip" : ""));
3143 break ;
3144
3145 case FPCEIL:
3146 case FPFLOOR:
3147 case FPTRUNC:
3148 case FPROUND:
3149 {
3150 char *op = "";
3151 char *type = "";
3152
3153 switch (insn->type) {
3154 case FPCEIL:
3155 op = "FP_RM_TOPINF";
3156 break;
3157 case FPFLOOR:
3158 op = "FP_RM_TOMINF";
3159 break;
3160 case FPTRUNC:
3161 op = "FP_RM_TOZERO";
3162 break;
3163 case FPROUND:
3164 op = "FP_RM_NEAREST";
3165 break;
3166 default:
3167 fprintf(stderr,"Error: Handled missing for FP reason code %d\n",insn->type);
3168 exit(1);
3169 }
8ad57737 3170
831f59a2
ILT
3171 switch (GETDATASIZEINSN(insn)) {
3172 case WORD :
3173 type = "fmt_word";
3174 break;
3175 case DOUBLEWORD :
3176 type = "fmt_long";
3177 break;
3178 default:
3179 fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
3180 exit(1);
3181 }
3182 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3183 printf(" SignalException(ReservedInstruction,instruction);\n");
3184 printf(" else\n");
3185 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
3186 }
3187 break ;
3188
3189 case FPCONVERT:
3190 {
3191 char *type = "";
3192 switch (GETDATASIZEINSN(insn)) {
3193 case SINGLE:
3194 type = "fmt_single";
3195 break;
3196 case DOUBLE:
3197 type = "fmt_double";
3198 break;
3199 case WORD:
3200 type = "fmt_word";
3201 break;
3202 case DOUBLEWORD:
3203 type = "fmt_long";
3204 break;
3205 default :
3206 fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn));
3207 exit(1);
3208 }
8ad57737 3209
831f59a2
ILT
3210 /* Not all combinations of conversion are valid at the
3211 moment: When converting to a fixed-point format, only
3212 floating-point sources are allowed. */
3213 printf(" if ((format == %s) | %s)\n",type,((insn->flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
3214 printf(" SignalException(ReservedInstruction,instruction);\n");
3215 printf(" else\n");
3216 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
3217 }
3218 break ;
3219
3220 case FPSUB:
3221 if (insn->flags & MULTIPLY) {
3222 char *type = "";
3223 switch (GETDATASIZEINSN(insn)) {
3224 case SINGLE:
3225 type = "fmt_single";
3226 break;
3227 case DOUBLE:
3228 type = "fmt_double";
3229 break;
3230 default:
3231 fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn));
3232 exit(1);
3233 }
3234 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);
3235 } else {
3236 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3237 printf(" SignalException(ReservedInstruction,instruction);\n");
3238 printf(" else\n");
3239 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3240 }
3241 break ;
3242
3243 case FPADD:
3244 if (insn->flags & MULTIPLY) {
3245 char *type = "";
3246 switch (GETDATASIZEINSN(insn)) {
3247 case SINGLE:
3248 type = "fmt_single";
3249 break;
3250 case DOUBLE:
3251 type = "fmt_double";
3252 break;
3253 default:
3254 fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn));
3255 exit(1);
3256 }
3257 if (insn->flags & NOT)
3258 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
3259 type, type, type, type, type, type, type);
3260 else
3261 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
3262 type, type, type, type, type, type);
3263 } else {
3264 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3265 printf(" SignalException(ReservedInstruction,instruction);\n");
3266 printf(" else\n");
3267 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
3268 }
3269 break ;
3270
3271 case FPCOMPARE:
3272 /* For the MIPS I,II or III there *MUST* be at least one
3273 instruction between the compare that sets a condition code
3274 and the branch that tests it. NOTE: However the hardware
3275 does not detect this condition. */
3276 /* Explicitly limit the operation to S and D formats: */
3277 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
3278 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3279 printf(" else {\n");
3280 if (doisa < 4) {
6389d856 3281 printf(" if (condition_code != 0)\n");
831f59a2
ILT
3282 printf(" SignalException(ReservedInstruction,instruction);\n") ;
3283 printf(" else\n");
3284 }
3285 printf(" {\n");
3286 printf(" int ignore = 0;\n");
3287 printf(" int less = 0;\n");
3288 printf(" int equal = 0;\n");
3289 printf(" int unordered = 1;\n");
3290 printf(" uword64 ofs = ValueFPR(fs,format);\n");
3291 printf(" uword64 oft = ValueFPR(ft,format);\n");
3292 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
3293 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
3294 printf(" FCSR |= FP_CAUSE(IO);\n");
3295 printf(" SignalException(FPE);\n");
3296 printf(" ignore = 1;\n");
3297 printf(" }\n");
3298 printf(" } else {\n");
3299 printf(" less = Less(ofs,oft,format);\n");
3300 printf(" equal = Equal(ofs,oft,format);\n");
3301 printf(" unordered = 0;\n");
3302 printf(" }\n");
3303 printf(" if (!ignore) {\n");
3304 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
3305 printf(" SETFCC(condition_code,condition);\n");
3306 printf(" }\n");
3307 printf(" }\n");
3308 printf(" }\n");
3309 break ;
3310
276c2d7d
GRK
3311/* start-sanitize-r5900 */
3312 case MADD:
3313 {
3314 char* pipeline = (insn->flags & PIPE1) ? "1" : "";
3315 int notsigned = (insn->flags & UNSIGNED);
3316 char* prodtype = notsigned ? "uword64" : "word64";
3317
3318 printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
3319 prodtype, prodtype, pipeline, pipeline,
3320 prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32"),
3321 prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32")
3322 );
c12e2e4c 3323 printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline );
276c2d7d 3324 printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline );
c12e2e4c 3325 printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline );
276c2d7d
GRK
3326 break;
3327 }
3328
3329 case MxSA:
3330 {
3331 if (insn->flags & TO)
3332 printf("SA = op1;\n");
3333 else
3334 printf("GPR[destreg] = SA;\n");
3335 break;
3336 }
3337
3338 case MTSAB:
3339 printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
3340 break;
3341
3342 case MTSAH:
3343 printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
3344 break;
3345
3346 case QFSRV:
3347 printf("int bytes = (SA / 8) %% 16;\n"); /* mod 16 to avoid garbage */
3348 printf("if (SA %% 8)\n");
3349 printf(" SignalException(ReservedInstruction,instruction);\n");
3350 printf("else\n");
3351 printf(" {\n");
3352 printf(" int i;\n");
3353 printf(" for(i=0;i<(16-bytes);i++)\n");
3354 printf(" GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
3355 printf(" for(;i<16;i++)\n");
3356 printf(" GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
3357 printf(" }\n");
3358 break;
3359
3360 case PADD:
3361 {
3362 char* op = (insn->flags & SUBTRACT) ? "-" : "+";
3363 char* name = name_for_data_len( insn );
3364 char* letter = letter_for_data_len( insn );
3365
3366 char* tmptype;
3367 char* maximum;
1e851d2c 3368 char* maxsat;
276c2d7d 3369 char* minimum;
c7cebfa3 3370 char* signletter;
276c2d7d
GRK
3371
3372 if ( insn->flags & UNSIGNED )
3373 {
1e851d2c 3374 tmptype = type_for_data_len( insn, 0/*unsigned*/ );
c7cebfa3 3375 signletter = "U";
276c2d7d 3376 maximum = umax_for_data_len( insn );
1e851d2c 3377 maxsat = (insn->flags & SUBTRACT) ? "0" : maximum;
276c2d7d
GRK
3378 minimum = 0;
3379 }
3380 else if ( insn->flags & SATURATE )
3381 {
1e851d2c 3382 tmptype = type_for_data_len( insn, 1/*signed*/ );
c7cebfa3
AC
3383 signletter = "S";
3384 maximum = max_for_data_len( insn );
1e851d2c 3385 maxsat = maximum;
c7cebfa3 3386 minimum = min_for_data_len( insn );
276c2d7d
GRK
3387 }
3388 else
3389 {
1e851d2c 3390 tmptype = type_for_data_len( insn, 1/*signed*/ );
c7cebfa3
AC
3391 signletter = "S";
3392 maximum = 0;
1e851d2c 3393 maxsat = 0;
c7cebfa3 3394 minimum = 0;
276c2d7d
GRK
3395 }
3396
1e851d2c
AC
3397 printf(" int i;\n");
3398 printf(" for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name );
3399 printf(" {\n");
3400 printf(" %s s = RS_%s%s(i);\n", tmptype, signletter, letter);
3401 printf(" %s t = RT_%s%s(i);\n", tmptype, signletter, letter);
3402 printf(" %s r = s %s t;\n", tmptype, op);
276c2d7d
GRK
3403 if ( maximum )
3404 {
1e851d2c
AC
3405 printf(" if (r > %s)\n", maximum);
3406 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter, letter, maxsat );
276c2d7d 3407 if ( minimum )
1e851d2c
AC
3408 {
3409 printf(" else if (r < %s)\n", minimum);
3410 printf(" GPR_%s%s(destreg,i) = %s;\n", signletter, letter, minimum );
3411 }
3412 printf(" else\n");
3413 printf(" ");
276c2d7d 3414 }
1e851d2c
AC
3415 printf(" GPR_%s%s(destreg,i) = r;\n", signletter, letter );
3416 printf(" }\n");
276c2d7d
GRK
3417 break;
3418 }
3419
3420 case PMULTH:
3421 {
3422 char* op;
3423 if ( insn->flags & SUBTRACT )
3424 op = "-";
3425 else if ( insn->flags & ADDITION )
3426 op = "+";
3427 else
3428 op = "";
3429
3430 printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op);
3431 printf(" LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op);
3432 printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op);
3433 printf(" HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op);
3434 printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op);
3435 printf(" LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op);
3436 printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op);
3437 printf(" HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op);
3438 break;
3439 }
3440
3441 case PMULTW:
3442 {
3443 char* op;
3444 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
1e851d2c 3445 char* prodtype = (insn->flags & UNSIGNED) ? "unsigned64" : "signed64";
276c2d7d
GRK
3446 char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64";
3447
276c2d7d
GRK
3448 if ( insn->flags & SUBTRACT )
3449 {
3450 op = "-";
1e851d2c
AC
3451 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor );
3452 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor );
276c2d7d
GRK
3453 }
3454 else if ( insn->flags & ADDITION )
3455 {
3456 op = "+";
1e851d2c
AC
3457 printf(" %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor );
3458 printf(" %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor );
276c2d7d
GRK
3459 }
3460 else
1e851d2c
AC
3461 {
3462 op = "";
3463 printf(" %s sum0 = 0;\n", prodtype );
3464 printf(" %s sum1 = 0;\n", prodtype );
3465 }
3466
3467 printf(" %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype, prodtype, sign, prodtype, sign );
3468 printf(" %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype, prodtype, sign, prodtype, sign );
276c2d7d 3469
1e851d2c
AC
3470 printf(" sum0 %s= prod0;\n", op );
3471 printf(" sum1 %s= prod1;\n", op );
276c2d7d 3472
1e851d2c
AC
3473 printf(" GPR_%sD(destreg,0) = sum0;\n", sign );
3474 printf(" GPR_%sD(destreg,1) = sum1;\n", sign );
276c2d7d 3475
1e851d2c
AC
3476 printf(" LO = SIGNEXTEND( sum0, 32 );\n");
3477 printf(" HI = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
3478 printf(" LO1 = SIGNEXTEND( sum1, 32 );\n");
3479 printf(" HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
276c2d7d
GRK
3480 break;
3481 }
3482
3483 case PDIVW:
1e851d2c
AC
3484 {
3485 char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
3486 int i;
3487 for (i = 0; i < 2; i ++)
3488 {
3489 char hi = (i == 0 ? ' ' : '1');
3490 int d = i * 2;
3491 printf("if (RT_UW(%d) != 0)\n", d );
3492 printf(" {\n");
3493 printf("LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi, sign, d, sign, d );
3494 printf("HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi, sign, d, sign, d );
3495 printf(" }\n");
3496 }
3497 break;
3498 }
276c2d7d
GRK
3499
3500 case PDIVBW:
1e851d2c
AC
3501 printf("signed32 devisor = RT_SH(0);\n");
3502 printf("if (devisor != 0)\n");
3503 printf(" {\n");
3504 printf(" LO_SW(0) = RS_SW(0) / devisor;\n");
3505 printf(" HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
3506 printf(" LO_SW(1) = RS_SW(1) / devisor;\n");
3507 printf(" HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
3508 printf(" LO_SW(2) = RS_SW(2) / devisor;\n");
3509 printf(" HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
3510 printf(" LO_SW(3) = RS_SW(3) / devisor;\n");
3511 printf(" HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
3512 printf(" }\n");
276c2d7d
GRK
3513 break;
3514
3515 case PADSBH:
3516 printf("int i;\n");
3517 printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
3518 printf(" GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
3519 printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
3520 printf(" GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
3521 break;
3522
3523 case PHMADDH:
3524 {
3525 char* op = (insn->flags & SUBTRACT) ? "-" : "+";
3526 printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op );
3527 printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op );
3528 printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op );
3529 printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op );
3530 }
3531 break;
3532
3533 case PSHIFT:
3534 {
3535 char* name = name_for_data_len( insn );
3536 char* letter = letter_for_data_len( insn );
3537 char* bits = bits_for_data_len( insn );
3538 char* shift = (insn->flags & RIGHT) ? ">>" : "<<";
3539 char* sign = (insn->flags & ARITHMETIC) ? "S" : "U";
3540
3541 printf("int shift_by = op1 & (%s-1);\n", bits );
3542 printf("int i;\n");
3543 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3544 printf(" GPR_%s%s(destreg,i) = ", sign, letter );
3545 if ( insn->flags & ARITHMETIC )
3546 printf("SIGNEXTEND( ");
3547 printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift );
3548 if ( insn->flags & ARITHMETIC )
3549 printf(", (%s-shift_by) )", bits );
3550 printf(";\n");
3551 break;
3552 }
3553
3554 case PSLLVW:
1e851d2c
AC
3555 printf("int s0 = (RS_UB(0) & 0x1F);\n");
3556 printf("int s1 = (RS_UB(8) & 0x1F);\n");
3557 printf("signed32 temp0 = RT_UW(0) << s0;\n");
3558 printf("signed32 temp1 = RT_UW(2) << s1;\n");
3559 printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
3560 printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
276c2d7d
GRK
3561 break;
3562
3563 case PSRLVW:
3564 printf("GPR_UD(destreg,0) = RT_UW(0) >> (RS_UB(0) & 0x1F);\n");
3565 printf("GPR_UD(destreg,1) = RT_UW(2) >> (RS_UB(8) & 0x1F);\n");
3566 break;
3567
3568 case PSRAVW:
3569 printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
3570 printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
3571 break;
3572
3573 case POP:
3574 {
3575 char* op1;
3576 char* op2;
3577
3578 if ( GET_OP_FROM_INSN(insn) == POP_AND )
3579 {
3580 op1 = "&";
3581 op2 = "";
3582 }
3583 else if ( GET_OP_FROM_INSN(insn) == POP_OR )
3584 {
3585 op1 = "|";
3586 op2 = "";
3587 }
3588 else if ( GET_OP_FROM_INSN(insn) == POP_NOR )
3589 {
3590 op1 = "|";
3591 op2 = "~";
3592 }
3593 else if ( GET_OP_FROM_INSN(insn) == POP_XOR )
3594 {
3595 op1 = "^";
3596 op2 = "";
3597 }
3598
3599 printf("int i;\n");
3600 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
3601 printf(" GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2, op1 );
3602 break;
3603 }
3604
3605 case PCMP:
3606 {
3607 char* name = name_for_data_len( insn );
3608 char* letter = letter_for_data_len( insn );
3609 char* maximum = umax_for_data_len( insn );
3610 char* op = (insn->flags & GT) ? ">" : "==";
3611
3612 printf("int i;\n");
3613 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3614 printf(" {\n");
3615 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n",
3616 letter, op, letter, letter, maximum );
3617 printf(" else GPR_S%s(destreg,i) = 0;\n", letter );
3618 printf(" }\n");
3619 break;
3620 }
3621
3622 case PMAXMIN:
3623 {
3624 char* name = name_for_data_len( insn );
3625 char* letter = letter_for_data_len( insn );
3626 char* op = (insn->flags & GT) ? ">" : "<";
3627
3628 printf("int i;\n");
3629 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3630 printf(" {\n");
3631 printf(" if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n",
3632 letter, op, letter, letter, letter );
3633 printf(" else GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3634 printf(" }\n");
3635 break;
3636 }
3637
3638 case PABS:
3639 {
3640 char* name = name_for_data_len( insn );
3641 char* letter = letter_for_data_len( insn );
3642
3643 printf("int i;\n");
3644 printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
3645 printf(" {\n");
3646 printf(" if (RT_S%s(i) < 0)\n", letter );
3647 printf(" GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter );
3648 printf(" else\n");
3649 printf(" GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
3650 printf(" }\n");
3651 break;
3652 }
3653
3654 case PCPYH:
3655 printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
3656 printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
3657 break;
3658
3659 case PCPYLD:
3660 printf("GPR_UD(destreg,0) = RT_UD(0);\n");
3661 printf("GPR_UD(destreg,1) = RS_UD(0);\n");
3662 break;
3663
3664 case PCPYUD:
3665 printf("GPR_UD(destreg,0) = RS_UD(1);\n");
3666 printf("GPR_UD(destreg,1) = RT_UD(1);\n");
3667 break;
3668
3669 case PEXCH:
3670 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3671 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3672 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3673 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3674 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3675 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3676 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3677 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3678 break;
3679
3680 case PEXCW:
3681 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3682 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3683 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3684 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3685 break;
3686
3687 case PEXOH:
3688 printf("GPR_UH(destreg,0) = RT_UH(2);\n");
3689 printf("GPR_UH(destreg,1) = RT_UH(1);\n");
3690 printf("GPR_UH(destreg,2) = RT_UH(0);\n");
3691 printf("GPR_UH(destreg,3) = RT_UH(3);\n");
3692 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3693 printf("GPR_UH(destreg,5) = RT_UH(5);\n");
3694 printf("GPR_UH(destreg,6) = RT_UH(4);\n");
3695 printf("GPR_UH(destreg,7) = RT_UH(7);\n");
3696 break;
3697
3698 case PEXOW:
3699 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3700 printf("GPR_UW(destreg,1) = RT_UW(1);\n");
3701 printf("GPR_UW(destreg,2) = RT_UW(0);\n");
3702 printf("GPR_UW(destreg,3) = RT_UW(3);\n");
3703 break;
3704
3705 case PEXTLB:
3706 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3707 printf("GPR_UB(destreg,1) = RS_UB(0);\n");
3708 printf("GPR_UB(destreg,2) = RT_UB(1);\n");
3709 printf("GPR_UB(destreg,3) = RS_UB(1);\n");
3710 printf("GPR_UB(destreg,4) = RT_UB(2);\n");
3711 printf("GPR_UB(destreg,5) = RS_UB(2);\n");
3712 printf("GPR_UB(destreg,6) = RT_UB(3);\n");
3713 printf("GPR_UB(destreg,7) = RS_UB(3);\n");
3714 printf("GPR_UB(destreg,8) = RT_UB(4);\n");
3715 printf("GPR_UB(destreg,9) = RS_UB(4);\n");
3716 printf("GPR_UB(destreg,10) = RT_UB(5);\n");
3717 printf("GPR_UB(destreg,11) = RS_UB(5);\n");
3718 printf("GPR_UB(destreg,12) = RT_UB(6);\n");
3719 printf("GPR_UB(destreg,13) = RS_UB(6);\n");
3720 printf("GPR_UB(destreg,14) = RT_UB(7);\n");
3721 printf("GPR_UB(destreg,15) = RS_UB(7);\n");
3722 break;
3723
3724 case PEXTLH:
3725 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3726 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3727 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3728 printf("GPR_UH(destreg,3) = RS_UH(1);\n");
3729 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3730 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3731 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3732 printf("GPR_UH(destreg,7) = RS_UH(3);\n");
3733 break;
3734
3735 case PEXTLW:
3736 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3737 printf("GPR_UW(destreg,1) = RS_UW(0);\n");
3738 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3739 printf("GPR_UW(destreg,3) = RS_UW(1);\n");
3740 break;
3741
3742 case PEXTUB:
3743 printf("GPR_UB(destreg,0) = RT_UB(8);\n");
3744 printf("GPR_UB(destreg,1) = RS_UB(8);\n");
3745 printf("GPR_UB(destreg,2) = RT_UB(9);\n");
3746 printf("GPR_UB(destreg,3) = RS_UB(9);\n");
3747 printf("GPR_UB(destreg,4) = RT_UB(10);\n");
3748 printf("GPR_UB(destreg,5) = RS_UB(10);\n");
3749 printf("GPR_UB(destreg,6) = RT_UB(11);\n");
3750 printf("GPR_UB(destreg,7) = RS_UB(11);\n");
3751 printf("GPR_UB(destreg,8) = RT_UB(12);\n");
3752 printf("GPR_UB(destreg,9) = RS_UB(12);\n");
3753 printf("GPR_UB(destreg,10) = RT_UB(13);\n");
3754 printf("GPR_UB(destreg,11) = RS_UB(13);\n");
3755 printf("GPR_UB(destreg,12) = RT_UB(14);\n");
3756 printf("GPR_UB(destreg,13) = RS_UB(14);\n");
3757 printf("GPR_UB(destreg,14) = RT_UB(15);\n");
3758 printf("GPR_UB(destreg,15) = RS_UB(15);\n");
3759 break;
3760
3761 case PEXTUH:
3762 printf("GPR_UH(destreg,0) = RT_UH(4);\n");
3763 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3764 printf("GPR_UH(destreg,2) = RT_UH(5);\n");
3765 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3766 printf("GPR_UH(destreg,4) = RT_UH(6);\n");
3767 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3768 printf("GPR_UH(destreg,6) = RT_UH(7);\n");
3769 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3770 break;
3771
3772 case PEXTUW:
3773 printf("GPR_UW(destreg,0) = RT_UW(2);\n");
3774 printf("GPR_UW(destreg,1) = RS_UW(2);\n");
3775 printf("GPR_UW(destreg,2) = RT_UW(3);\n");
3776 printf("GPR_UW(destreg,3) = RS_UW(3);\n");
3777 break;
3778
3779 case PPACB:
3780 printf("GPR_UB(destreg,0) = RT_UB(0);\n");
3781 printf("GPR_UB(destreg,1) = RT_UB(2);\n");
3782 printf("GPR_UB(destreg,2) = RT_UB(4);\n");
3783 printf("GPR_UB(destreg,3) = RT_UB(6);\n");
3784 printf("GPR_UB(destreg,4) = RT_UB(8);\n");
3785 printf("GPR_UB(destreg,5) = RT_UB(10);\n");
3786 printf("GPR_UB(destreg,6) = RT_UB(12);\n");
3787 printf("GPR_UB(destreg,7) = RT_UB(14);\n");
3788 printf("GPR_UB(destreg,8) = RS_UB(0);\n");
3789 printf("GPR_UB(destreg,9) = RS_UB(2);\n");
3790 printf("GPR_UB(destreg,10) = RS_UB(4);\n");
3791 printf("GPR_UB(destreg,11) = RS_UB(6);\n");
3792 printf("GPR_UB(destreg,12) = RS_UB(8);\n");
3793 printf("GPR_UB(destreg,13) = RS_UB(10);\n");
3794 printf("GPR_UB(destreg,14) = RS_UB(12);\n");
3795 printf("GPR_UB(destreg,15) = RS_UB(14);\n");
3796 break;
3797
3798 case PPACH:
3799 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3800 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3801 printf("GPR_UH(destreg,2) = RT_UH(4);\n");
3802 printf("GPR_UH(destreg,3) = RT_UH(6);\n");
3803 printf("GPR_UH(destreg,4) = RS_UH(0);\n");
3804 printf("GPR_UH(destreg,5) = RS_UH(2);\n");
3805 printf("GPR_UH(destreg,6) = RS_UH(4);\n");
3806 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3807 break;
3808
3809 case PPACW:
3810 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3811 printf("GPR_UW(destreg,1) = RT_UW(2);\n");
3812 printf("GPR_UW(destreg,2) = RS_UW(0);\n");
3813 printf("GPR_UW(destreg,3) = RS_UW(2);\n");
3814 break;
3815
3816 case PREVH:
3817 printf("GPR_UH(destreg,0) = RT_UH(3);\n");
3818 printf("GPR_UH(destreg,1) = RT_UH(2);\n");
3819 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3820 printf("GPR_UH(destreg,3) = RT_UH(0);\n");
3821 printf("GPR_UH(destreg,4) = RT_UH(7);\n");
3822 printf("GPR_UH(destreg,5) = RT_UH(6);\n");
3823 printf("GPR_UH(destreg,6) = RT_UH(5);\n");
3824 printf("GPR_UH(destreg,7) = RT_UH(4);\n");
3825 break;
3826
3827 case PROT3W:
3828 printf("GPR_UW(destreg,0) = RT_UW(0);\n");
3829 printf("GPR_UW(destreg,1) = RT_UW(3);\n");
3830 printf("GPR_UW(destreg,2) = RT_UW(1);\n");
3831 printf("GPR_UW(destreg,3) = RT_UW(2);\n");
3832 break;
3833
3834 case PINTH:
3835 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3836 printf("GPR_UH(destreg,1) = RS_UH(4);\n");
3837 printf("GPR_UH(destreg,2) = RT_UH(1);\n");
3838 printf("GPR_UH(destreg,3) = RS_UH(5);\n");
3839 printf("GPR_UH(destreg,4) = RT_UH(2);\n");
3840 printf("GPR_UH(destreg,5) = RS_UH(6);\n");
3841 printf("GPR_UH(destreg,6) = RT_UH(3);\n");
3842 printf("GPR_UH(destreg,7) = RS_UH(7);\n");
3843 break;
3844
3845 case PINTOH:
3846 printf("GPR_UH(destreg,0) = RT_UH(0);\n");
3847 printf("GPR_UH(destreg,1) = RS_UH(0);\n");
3848 printf("GPR_UH(destreg,2) = RT_UH(2);\n");
3849 printf("GPR_UH(destreg,3) = RS_UH(2);\n");
3850 printf("GPR_UH(destreg,4) = RT_UH(4);\n");
3851 printf("GPR_UH(destreg,5) = RS_UH(4);\n");
3852 printf("GPR_UH(destreg,6) = RT_UH(6);\n");
3853 printf("GPR_UH(destreg,7) = RS_UH(6);\n");
3854 break;
3855
3856 case PMXX: /* Parallel move HI or LO / TO or FROM */
3857 {
3858 if ( (insn->flags & (HI|FROM)) == (HI|FROM) )
3859 {
3860 printf("GPR_SD(destreg,0) = HI;\n");
3861 printf("GPR_SD(destreg,1) = HI1;\n");
3862 }
3863 else if ( (insn->flags & (LO|FROM)) == (LO|FROM) )
3864 {
3865 printf("GPR_SD(destreg,0) = LO;\n");
3866 printf("GPR_SD(destreg,1) = LO1;\n");
3867 }
3868 else if ( (insn->flags & (HI|TO)) == (HI|TO) )
3869 {
3870 printf("HI = RS_SD(0);\n");
3871 printf("HI1 = RS_SD(1);\n");
3872 }
3873 else if ( (insn->flags & (LO|TO)) == (LO|TO) )
3874 {
3875 printf("LO = RS_SD(0);\n");
3876 printf("LO1 = RS_SD(1);\n");
3877 }
3878 break;
3879 }
3880
3881 case PMTHL:
3882 printf("LO_UW(0) = RS_UW(0);\n");
3883 printf("HI_UW(0) = RS_UW(1);\n");
3884 printf("LO_UW(2) = RS_UW(2);\n");
3885 printf("HI_UW(2) = RS_UW(3);\n");
3886 break;
3887
3888 case PMFHL:
3889 printf("if (op1 == 0)\n");
3890 printf(" {\n");
3891 printf(" GPR_UW(destreg,0) = LO_UW(0);\n");
3892 printf(" GPR_UW(destreg,1) = HI_UW(0);\n");
3893 printf(" GPR_UW(destreg,2) = LO_UW(2);\n");
3894 printf(" GPR_UW(destreg,3) = HI_UW(2);\n");
3895 printf(" }\n");
3896 printf("else if (op1 == 1)\n");
3897 printf(" {\n");
3898 printf(" GPR_UW(destreg,0) = LO_UW(1);\n");
3899 printf(" GPR_UW(destreg,1) = HI_UW(1);\n");
3900 printf(" GPR_UW(destreg,2) = LO_UW(3);\n");
3901 printf(" GPR_UW(destreg,3) = HI_UW(3);\n");
3902 printf(" }\n");
3903 printf("else if (op1 == 2)\n");
3904 printf(" {\n");
1e851d2c
AC
3905 printf(" /* NOTE: This code implements a saturate according to the\n");
3906 printf(" figure on page B-115 and not according to the\n");
3907 printf(" definition on page B-113 */\n");
3908 printf(" signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
3909 printf(" signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
3910 printf(" signed64 x000000007FFFFFFF = LSMASK64 (31);\n");
3911 printf(" signed64 xFFFFFFFF80000000 = MSMASK64 (33);\n");
3912 printf(" signed64 x7FFFFFFFFFFFFFFF = LSMASK64 (63);\n");
3913 printf(" signed64 x8000000000000000 = MSMASK64 (1);\n");
3914 printf(" signed64 x0000000080000000 = x000000007FFFFFFF + 1;\n");
3915 printf(" signed64 minus0000000080000000 = -x0000000080000000;\n");
3916 printf(" if ( t > x000000007FFFFFFF )\n");
3917 printf(" GPR_SD(destreg,0) = x000000007FFFFFFF;\n");
3918 printf(" else if ( t < minus0000000080000000 )\n");
3919 printf(" GPR_SD(destreg,0) = minus0000000080000000;\n");
3920 printf(" else\n");
3921 printf(" GPR_SD(destreg,0) = t;\n");
3922 printf(" if ( u > x000000007FFFFFFF )\n");
3923 printf(" GPR_SD(destreg,1) = x000000007FFFFFFF;\n");
3924 printf(" else if ( u < minus0000000080000000 )\n");
3925 printf(" GPR_SD(destreg,1) = minus0000000080000000;\n");
276c2d7d 3926 printf(" else\n");
1e851d2c 3927 printf(" GPR_SD(destreg,1) = u;\n");
276c2d7d
GRK
3928 printf(" }\n");
3929 printf("else if (op1 == 3)\n");
3930 printf(" {\n");
3931 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3932 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3933 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
3934 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
3935 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3936 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3937 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3938 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3939 printf(" }\n");
3940 printf("else if (op1 == 4)\n");
3941 printf(" {\n");
1e851d2c 3942 printf(" if (LO_SW(0) > 0x7FFF)\n");
276c2d7d 3943 printf(" GPR_UH(destreg,0) = 0x7FFF;\n");
1e851d2c 3944 printf(" else if (LO_SW(0) < -0x8000)\n");
276c2d7d
GRK
3945 printf(" GPR_UH(destreg,0) = 0x8000;\n");
3946 printf(" else\n");
3947 printf(" GPR_UH(destreg,0) = LO_UH(0);\n");
3948
1e851d2c 3949 printf(" if (LO_SW(1) > 0x7FFF)\n");
276c2d7d 3950 printf(" GPR_UH(destreg,1) = 0x7FFF;\n");
1e851d2c 3951 printf(" else if (LO_SW(1) < -0x8000)\n");
276c2d7d
GRK
3952 printf(" GPR_UH(destreg,1) = 0x8000;\n");
3953 printf(" else\n");
3954 printf(" GPR_UH(destreg,1) = LO_UH(2);\n");
3955
1e851d2c
AC
3956 printf(" if (HI_SW(0) > 0x7FFF)\n");
3957 printf(" GPR_UH(destreg,2) = 0x7FFF;\n");
3958 printf(" else if (HI_SW(0) < -0x8000)\n");
3959 printf(" GPR_UH(destreg,2) = 0x8000;\n");
276c2d7d 3960 printf(" else\n");
1e851d2c 3961 printf(" GPR_UH(destreg,2) = HI_UH(0);\n");
276c2d7d 3962
1e851d2c
AC
3963 printf(" if (HI_SW(1) > 0x7FFF)\n");
3964 printf(" GPR_UH(destreg,3) = 0x7FFF;\n");
3965 printf(" else if (HI_SW(1) < -0x8000)\n");
3966 printf(" GPR_UH(destreg,3) = 0x8000;\n");
276c2d7d 3967 printf(" else\n");
1e851d2c 3968 printf(" GPR_UH(destreg,3) = HI_UH(2);\n");
276c2d7d 3969
1e851d2c 3970 printf(" if (LO_SW(2) > 0x7FFF)\n");
276c2d7d 3971 printf(" GPR_UH(destreg,4) = 0x7FFF;\n");
1e851d2c 3972 printf(" else if (LO_SW(2) < -0x8000)\n");
276c2d7d
GRK
3973 printf(" GPR_UH(destreg,4) = 0x8000;\n");
3974 printf(" else\n");
3975 printf(" GPR_UH(destreg,4) = LO_UH(4);\n");
3976
1e851d2c 3977 printf(" if (LO_SW(3) > 0x7FFF)\n");
276c2d7d 3978 printf(" GPR_UH(destreg,5) = 0x7FFF;\n");
1e851d2c 3979 printf(" else if (LO_SW(3) < -0x8000)\n");
276c2d7d
GRK
3980 printf(" GPR_UH(destreg,5) = 0x8000;\n");
3981 printf(" else\n");
3982 printf(" GPR_UH(destreg,5) = LO_UH(6);\n");
3983
1e851d2c 3984 printf(" if (HI_SW(2) > 0x7FFF)\n");
276c2d7d 3985 printf(" GPR_UH(destreg,6) = 0x7FFF;\n");
1e851d2c 3986 printf(" else if (HI_SW(2) < -0x8000)\n");
276c2d7d
GRK
3987 printf(" GPR_UH(destreg,6) = 0x8000;\n");
3988 printf(" else\n");
3989 printf(" GPR_UH(destreg,6) = HI_UH(4);\n");
3990
1e851d2c 3991 printf(" if (HI_SW(3) > 0x7FFF)\n");
276c2d7d 3992 printf(" GPR_UH(destreg,7) = 0x7FFF;\n");
1e851d2c 3993 printf(" else if (HI_SW(3) < -0x8000)\n");
276c2d7d
GRK
3994 printf(" GPR_UH(destreg,7) = 0x8000;\n");
3995 printf(" else\n");
3996 printf(" GPR_UH(destreg,7) = HI_UH(6);\n");
3997
3998 printf(" }\n");
3999 break;
4000
4001 case PLZCW:
4002 printf("unsigned long value;\n");
4003 printf("int test;\n");
4004 printf("int count;\n");
4005 printf("int i;\n");
4006
4007 printf("value = RS_UW(0);\n");
4008 printf("count = 0;\n");
4009 printf("test = !!(value & (1 << 31));\n");
4010 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4011 printf(" count++;\n");
4012 printf("GPR_UW(destreg,0) = count;\n");
4013
4014 printf("value = RS_UW(1);\n");
4015 printf("count = 0;\n");
4016 printf("test = !!(value & (1 << 31));\n");
4017 printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
4018 printf(" count++;\n");
4019 printf("GPR_UW(destreg,1) = count;\n");
4020 break;
4021
4022 case PEXT5:
4023 printf("int i;\n");
4024 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4025 printf(" {\n");
1e851d2c 4026 printf(" unsigned32 x = RT_UW(i);\n");
64435234 4027 printf(" GPR_UW(destreg,i) = ((x & (1 << 15)) << (31 - 15)) \n");
276c2d7d
GRK
4028 printf(" | ((x & (31 << 10)) << (19 - 10)) \n");
4029 printf(" | ((x & (31 << 5)) << (11 - 5)) \n");
4030 printf(" | ((x & (31 << 0)) << (3 - 0)); \n");
4031 printf(" }\n");
4032 break;
4033
4034 case PPAC5:
4035 printf("int i;\n");
4036 printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
4037 printf(" {\n");
1e851d2c 4038 printf(" unsigned32 x = RT_UW(i);\n");
649625bb 4039 printf(" GPR_UW(destreg,i) = ((x & (1 << 31)) >> (31 - 15)) \n");
276c2d7d
GRK
4040 printf(" | ((x & (31 << 19)) >> (19 - 10)) \n");
4041 printf(" | ((x & (31 << 11)) >> (11 - 5)) \n");
4042 printf(" | ((x & (31 << 3)) >> (3 - 0)); \n");
4043 printf(" }\n");
4044 break;
4045/* end-sanitize-r5900 */
4046
4047 case NYI:
4048 fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
4049
4050 printf("SignalException(ReservedInstruction,instruction);\n");
4051 break;
4052
831f59a2
ILT
4053 default:
4054 fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
4055 exit(6) ;
4056 }
8ad57737
JSC
4057}
4058
4059/*---------------------------------------------------------------------------*/
4060
4061/* The command-line feature controls are presented in a similar style
4062 to those offered by GCC, in the aim of providing a consistent
4063 interface to the user. */
4064typedef enum {
4065 T_NONE, /* no argument - mask and value fields control "feature" definition */
4066 T_NUM, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
4067 T_STRING /* string argument - optionally prcededed by '=' */
4068} mactypes;
4069
4070struct {
4071 char *name;
4072 mactypes type;
4073 unsigned int mask;
4074 unsigned int value;
4075 char *desc;
4076} machine_options[] = {
4077 {"ips", T_NUM, MASK_ISA,0,"\tSelect MIPS ISA version"},
4078 {"cpu", T_STRING,0,0,"\t\tSelect particular MIPS architecture"},
4079 {"gp64", T_NONE, FEATURE_GP64,FEATURE_GP64,"\t\t\tSelect 64bit GP registers"},
4080 {"gp32", T_NONE, FEATURE_GP64,0,"\t\t\tSelect 32bit GP registers"},
4081 {"no-fp", T_NONE, FEATURE_HASFPU,0,"\t\tDisable FP simulation"},
8ad57737
JSC
4082 {"single-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),(FEATURE_FPSINGLE | FEATURE_HASFPU),"\t\tSelect single precision only FPU"},
4083 {"double-float",T_NONE, (FEATURE_FPSINGLE | FEATURE_HASFPU),FEATURE_HASFPU,"\t\tSelect double precision FPU"},
4084 {0, T_NONE, 0,0}
4085};
4086
4087/* The following architecture identies are those accepted by the "-mcpu" option: */
4088struct architectures {
4089 const char *name; /* ASCII string identifier for command-line, no white-space allowed */
4090 unsigned int idflag; /* or-ed into "isa" value */
4091};
4092
4093static const struct architectures available_architectures[] = {
4094 {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
276c2d7d
GRK
4095 /* start-sanitize-r5900 */
4096 {"5900",ARCH_R5900},
4097 /* end-sanitize-r5900 */
8ad57737
JSC
4098 {0, 0} /* terminator */
4099};
4100
4101/*---------------------------------------------------------------------------*/
4102
4103static void
4104usage(name)
4105 char *name;
4106{
4107 int loop;
4108
4109 fprintf(stderr,"%s: Construct a MIPS simulator engine.\n",name);
4110
4111 fprintf(stderr,"\
4112The output of this program is a block of 'C' code designed to be\n\
4113included into the main simulation control loop of a device specific\n\
4114simulator.\n");
4115
4116 fprintf(stderr,"\nOptions:\n");
4117 fprintf(stderr," -h --help\t\tProvide this help text\n");
4118 fprintf(stderr," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
4119 fprintf(stderr," -w --warnings\t\tEnable all the simulator engine warnings\n");
4120
4121 for (loop = 0; (machine_options[loop].name != 0); loop++) {
4122 fprintf(stderr," -m%s",machine_options[loop].name);
4123 switch (machine_options[loop].type) {
4124 case T_NUM :
4125 fprintf(stderr,"N (range 0..%d)",machine_options[loop].mask);
4126 case T_NONE :
4127 break;
4128
4129 case T_STRING :
4130 fprintf(stderr,"=name");
4131 break;
4132
4133 default :
831f59a2 4134 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type);
8ad57737
JSC
4135 exit(1);
4136 }
4137 fprintf(stderr,"%s\n",machine_options[loop].desc);
4138 }
4139
4140 fprintf(stderr,"\nAvailable \"-mcpu\" architectures: ");
4141 for (loop = 0; (available_architectures[loop].name != 0); loop++)
4142 fprintf(stderr,"%s ",available_architectures[loop].name);
4143 fprintf(stderr,"\n\n");
4144
4145 fprintf(stderr,"\
4146The \"trace\" and \"warnings\" options do not define the output stream.\n\
4147They only inform the code that includes the constructed engine to provide\n\
4148the required features.\n\n\
4149The \"-mips0\" option forces the construction of a simulator supporting\n\
4150the highest available MIPS ISA supported.\n");
4151
4152 return;
4153}
4154
4155/*---------------------------------------------------------------------------*/
4156
4157int
4158main(argc,argv)
4159 int argc;
4160 char **argv;
4161{
4162 int c;
4163 char *progname = argv[0];
4164 unsigned int doarch = DEF_ISA;
4165 unsigned int features = 0; /* default state */
4166
4167 if (DEF_FP)
4168 features |= FEATURE_HASFPU;
4169 if (!DEF_PROC64)
4170 features |= FEATURE_PROC32;
4171 if (DEF_FPSINGLE)
4172 features |= FEATURE_FPSINGLE;
4173
4174 if (features & FEATURE_PROC32)
8bae0a0c 4175 features &= ~FEATURE_GP64;
8ad57737 4176 else
8bae0a0c 4177 features |= FEATURE_GP64;
8ad57737
JSC
4178
4179 while (1) {
8ad57737
JSC
4180 int option_index = 0;
4181 static struct option cmdline[] = {
4182 {"fast", 0,0,'f'},
4183 {"help", 0,0,'h'},
4184 {"warnings",0,0,'w'},
4185 {0, 0,0,0}
4186 };
4187
4188 c = getopt_long(argc,argv,"hm:tw",cmdline,&option_index);
4189 if (c == -1)
4190 break ; /* out of the while loop */
4191
4192 switch (c) {
4193 case 'h' : /* help */
4194 usage(progname);
4195 exit(0);
4196
4197 case 'f' : /* fast */
4198 features |= FEATURE_FAST;
4199 break;
4200
4201 case 'w' : /* warnings */
4202 features |= FEATURE_WARNINGS;
4203 /* TODO: Future extension: Allow better control over the warnings generated:
4204 disable warnings -wnone ~FEATURE_WARNINGS
4205 all possible warnings -wall FEATURE_WARNINGS
4206 pipeline stall occuring -wstall FEATURE_WARN_STALL
4207 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
4208 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
4209 bad r31 use -wr31 FEATURE_WARN_R31
4210 undefined results -wresult FEATURE_WARN_RESULT
4211 */
4212 break;
4213
4214 case 'm' : /* machine options */
4215 {
4216 int loop;
4217
4218 for (loop = 0; (machine_options[loop].name != 0); loop++)
4219 if (strncmp(machine_options[loop].name,optarg,strlen(machine_options[loop].name)) == 0) {
4220 char *loptarg = (optarg + strlen(machine_options[loop].name));
4221 switch (machine_options[loop].type) {
4222 case T_NONE :
4223 if (*loptarg) {
4224 fprintf(stderr,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname,loptarg,machine_options[loop].name);
4225 exit(1);
4226 }
4227 features &= ~(machine_options[loop].mask);
4228 features |= machine_options[loop].value;
4229 break;
4230
4231 case T_NUM :
4232 if (*loptarg && *loptarg == '=')
4233 loptarg++;
4234
4235 if (strcmp(machine_options[loop].name,"ips") == 0) {
4236 unsigned int num;
4237
4238 if (!*loptarg) {
4239 fprintf(stderr,"%s: ISA number expected after -mips\n",progname);
4240 exit(1);
4241 }
4242
64d538ce 4243 num = my_strtoul(loptarg,&loptarg,10);
8ad57737
JSC
4244
4245 if ((num == ULONG_MAX) && (errno = ERANGE)) {
4246 fprintf(stderr,"%s: Invalid number given to -mips option\n",progname);
4247 exit(1);
4248 }
4249
4250 if (*loptarg) {
4251 fprintf(stderr,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname,loptarg);
4252 exit(1);
4253 }
4254
4255 if (num > MASK_ISA) {
4256 fprintf(stderr,"%s: ISA number %d outside acceptable range (0..%d)\n",progname,num,MASK_ISA);
4257 exit(1);
4258 }
4259
4260 doarch = ((doarch & ~MASK_ISA) | num);
4261 if ((num == 0) || (num > 2)) {
8bae0a0c
JSC
4262 if ((features & FEATURE_PROC32) || !(features & FEATURE_GP64))
4263 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp64\n",progname,num);
4264 features |= FEATURE_GP64;
8ad57737
JSC
4265 features &= ~FEATURE_PROC32;
4266 } else {
8bae0a0c
JSC
4267 if (!(features & FEATURE_PROC32) || (features & FEATURE_GP64))
4268 fprintf(stderr,"%s: Warning: -mips%d forcing -mgp32\n",progname,num);
4269 features &= ~FEATURE_GP64;
8ad57737
JSC
4270 features |= FEATURE_PROC32;
4271 }
4272 } else {
4273 fprintf(stderr,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname,optarg);
4274 exit(1);
4275 }
4276 break;
4277
4278 case T_STRING :
4279 if (*loptarg && *loptarg == '=')
4280 loptarg++;
4281
4282 if (strcmp(machine_options[loop].name,"cpu") == 0) {
4283 int archloop;
4284
4285 if (!*loptarg) {
4286 fprintf(stderr,"%s: Architecture identifier expected after -mcpu\n",progname);
4287 exit(1);
4288 }
4289
4290 for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
4291 if ((*loptarg == 'v') || (*loptarg == 'V'))
831f59a2 4292 loptarg++;
8ad57737 4293
831f59a2
ILT
4294 if ((*loptarg == 'r') || (*loptarg == 'R'))
4295 loptarg++;
8ad57737
JSC
4296
4297 if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
4298 doarch |= available_architectures[archloop].idflag;
4299 break;
4300 }
4301 }
4302
4303 if (available_architectures[archloop].name == 0) {
4304 fprintf(stderr,"%s: Unrecognised MIPS architecture \"%s\"\n",progname,loptarg);
4305 exit(1);
4306 }
4307 } else {
4308 fprintf(stderr,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname,optarg);
4309 exit(1);
4310 }
4311 break;
4312
4313 default :
4314 fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",progname,machine_options[loop].type);
4315 exit(1);
4316 }
4317 break;
4318 }
4319
4320 if (machine_options[loop].name == 0) {
4321 fprintf(stderr,"%s: Unrecognised option: -m%s\n",progname,optarg);
4322 exit(1);
4323 }
4324 }
4325 break;
4326
4327 case '?' :
4328 /* An error message should already have been displayed */
4329 exit(1);
4330
4331 default :
4332 fprintf(stderr,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname,c);
4333 exit(1);
4334 }
4335 }
4336
4337 if (optind < argc) {
4338 fprintf(stderr,"%s: Spurios non-option arguments ",progname);
4339 while (optind < argc)
4340 fprintf(stderr,"\"%s\" ",argv[optind++]);
4341 fprintf(stderr,"\n");
4342 exit(1);
4343 }
4344
4345 if ((features & FEATURE_FAST) && (features & FEATURE_WARNINGS))
4346 fprintf(stderr,"Warning: Fast model generation selected, along with trace or warnings.\n");
4347
4348 process_instructions(doarch,features) ;
4349 return(0) ;
4350}
4351
4352/*---------------------------------------------------------------------------*/
64d538ce
ILT
4353
4354/* We can't assume that the compiler for the build system has strtoul,
4355 so we provide our own copy. */
4356
4357/*
4358 * Copyright (c) 1990 Regents of the University of California.
4359 * All rights reserved.
4360 *
4361 * Redistribution and use in source and binary forms, with or without
4362 * modification, are permitted provided that the following conditions
4363 * are met:
4364 * 1. Redistributions of source code must retain the above copyright
4365 * notice, this list of conditions and the following disclaimer.
4366 * 2. Redistributions in binary form must reproduce the above copyright
4367 * notice, this list of conditions and the following disclaimer in the
4368 * documentation and/or other materials provided with the distribution.
4369 * 3. All advertising materials mentioning features or use of this software
4370 * must display the following acknowledgement:
4371 * This product includes software developed by the University of
4372 * California, Berkeley and its contributors.
4373 * 4. Neither the name of the University nor the names of its contributors
4374 * may be used to endorse or promote products derived from this software
4375 * without specific prior written permission.
4376 *
4377 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4378 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4379 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4380 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
4381 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4382 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4383 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4384 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4385 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4386 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4387 * SUCH DAMAGE.
4388 */
4389
4390/*
4391 * Convert a string to an unsigned long integer.
4392 *
4393 * Ignores `locale' stuff. Assumes that the upper and lower case
4394 * alphabets and digits are each contiguous.
4395 */
4396static unsigned long
4397my_strtoul(nptr, endptr, base)
4398 const char *nptr;
4399 char **endptr;
4400 register int base;
4401{
4402 register const char *s = nptr;
4403 register unsigned long acc;
4404 register int c;
4405 register unsigned long cutoff;
4406 register int neg = 0, any, cutlim;
4407
4408 /*
4409 * See strtol for comments as to the logic used.
4410 */
4411 do {
4412 c = *s++;
4413 } while (isspace(c));
4414 if (c == '-') {
4415 neg = 1;
4416 c = *s++;
4417 } else if (c == '+')
4418 c = *s++;
4419 if ((base == 0 || base == 16) &&
4420 c == '0' && (*s == 'x' || *s == 'X')) {
4421 c = s[1];
4422 s += 2;
4423 base = 16;
4424 }
4425 if (base == 0)
4426 base = c == '0' ? 8 : 10;
4427 cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
4428 cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
4429 for (acc = 0, any = 0;; c = *s++) {
4430 if (isdigit(c))
4431 c -= '0';
4432 else if (isalpha(c))
4433 c -= isupper(c) ? 'A' - 10 : 'a' - 10;
4434 else
4435 break;
4436 if (c >= base)
4437 break;
831f59a2 4438 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
64d538ce
ILT
4439 any = -1;
4440 else {
4441 any = 1;
4442 acc *= base;
4443 acc += c;
4444 }
4445 }
4446 if (any < 0) {
4447 acc = ULONG_MAX;
4448 errno = ERANGE;
4449 } else if (neg)
4450 acc = -acc;
4451 if (endptr != 0)
4452 *endptr = (char *) (any ? s - 1 : nptr);
4453 return (acc);
4454}
4455
4456/*---------------------------------------------------------------------------*/
4457
8ad57737 4458/*> EOF gencode.c <*/
276c2d7d
GRK
4459
4460
4461
4462
4463
4464
4465
This page took 0.266442 seconds and 4 git commands to generate.