2 /* Instruction handling support for the MIPS architecture simulator.
4 This file is part of the MIPS sim
6 THIS SOFTWARE IS NOT COPYRIGHTED
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.
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.
22 #define DEBUG (1) /* Just for testing */
25 /* All output sent to stdout is for the simulator engine. All program
26 related warnings and errors should be sent to stderr. */
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
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.
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).
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). */
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. */
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. */
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
100 /*---------------------------------------------------------------------------*/
102 /* Program defaults */
104 #define DEF_PROC64 (1 == 1)
105 #define DEF_FP (1 == 1)
106 #define DEF_FPSINGLE (1 == 0)
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 */
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 */
121 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
123 #define FEATURE_WARNINGS (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
126 /* FEATURE_WARN_STALL */
127 /* If MIPS I we want to raise a warning if an attempt is made to
128 access Rn in an instruction immediately following an Rn update
129 "WARNING : Invalid value read". The simulator engine is designed
130 that the previous value is read in such cases, to allow programs
131 that make use of this feature to execute. */
132 /* If MIPS II or later, attempting to read a register before the
133 update has completed will generate a "WARNING : Processor stall"
134 message (since the processor will lock the pipeline until the value
135 becomes available). */
137 /* FEATURE_WARN_LOHI */
138 /* Warn if an attempt is made to read the HI/LO registers before the
139 update has completed, or if an attempt is made to update the
140 registers whilst an update is occurring. */
142 /* FEATURE_WARN_ZERO */
143 /* Notify the user if an attempt is made to use GPR 0 as a destination. */
145 /* FEATURE_WARN_R31 */
146 /* Notify the user if register r31 (the default procedure call return
147 address) is used unwisely. e.g. If r31 is used as the source in a
148 branch-and-link instruction, it would mean that an exception in the
149 delay slot instruction would not allow the branch to be re-started
150 (since r31 will have been overwritten by the link operation during
151 the first execution of the branch). */
153 /* FEATURE_WARN_RESULT */
154 /* Certain instructions do not raise exceptions when invalid operands
155 are given, they will just result in undefined values being
156 generated. This option controls whether the simulator flags such
159 /*---------------------------------------------------------------------------*/
166 #include "ansidecl.h"
167 #include "opcode/mips.h"
169 /* FIXME: ansidecl.h defines AND. */
173 #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
176 static unsigned long my_strtoul ();
180 #define TRUE (1 == 1)
181 #define FALSE (1 == 0)
185 /*---------------------------------------------------------------------------*/
187 /* Holding the instruction table this way makes it easier to check the
188 instruction values defined, and to add instructions to the
189 system. However, it makes the process of constructing the simulator
190 a bit more complicated: */
192 /* The "bitmap" is encoded as follows (NOTE: Only lower-case
193 alphabetic characters should be used, since the letter ordinal is
194 used as a bit position): */
196 typedef struct operand_encoding
{
197 char id
; /* character identifier */
198 int fpos
; /* first bit position */
199 int flen
; /* field length in bits */
205 /* Values for the "flags" field: */
206 #define OP_NONE (0 << 0) /* To keep the source tidy */
207 #define OP_GPR (1 << 0) /* Get operand from integer register bank */
208 #define OP_SIGNX (1 << 1) /* Sign-extend the operand */
209 #define OP_SHIFT2 (1 << 2) /* Shift field left by 2 */
210 #define OP_BITS5 (1 << 3) /* Only take the lo 5-bits of the operand */
212 struct operand_encoding opfields
[] = {
213 {'0',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit zero */
214 {'1',-1,-1,"", "", (OP_NONE
)}, /* special case for explicit one */
215 {'?',-1,-1,"", "", (OP_NONE
)}, /* undefined (do not care at this level) */
216 /* The rest are the explicit operand fields: */
217 {'a', 6, 5,"int", "op1", (OP_NONE
)}, /* shift amount (or hint) */
218 {'b',21, 5,"int", "fr", (OP_NONE
)}, /* fr register */
219 {'c',16, 1,"int", "boolean", (OP_NONE
)}, /* TRUE or FALSE boolean */
220 {'d',11, 5,"int", "destreg", (OP_NONE
)}, /* integer destination/rd register */
221 {'e', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-3bits must be zero) */
222 {'f',17, 1,"int", "likely", (OP_NONE
)}, /* set if branch LIKELY */
223 {'g',16, 5,"t_reg", "op2", (OP_GPR
)}, /* integer source rt register */
224 {'h', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-1bit must be zero) */
225 {'i', 0,16,"t_reg", "op2", (OP_SIGNX
)}, /* signed immediate (op2) */
226 {'j', 0,26,"ut_reg","op1", (OP_SHIFT2
)},/* shifted left 2 bits and combined with hi-order bits of address in the delay slot */
227 {'k',16, 5,"int", "ft", (OP_NONE
)},
228 {'l', 0,16,"t_reg", "offset", (OP_SIGNX
| OP_SHIFT2
)}, /* signed offset shifted left 2 to make 18bit signed offset */
229 {'m',21, 3,"int", "format", (OP_NONE
)}, /* FP format field */
230 {'n',16, 5,"int", "hint", (OP_NONE
)}, /* hint */
231 {'o',21, 5,"t_reg", "op1", (OP_GPR
| OP_BITS5
)}, /* integer source/rs register (but never treated as 32bit word) */
232 {'p', 8, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
233 {'q',18, 3,"int", "condition_code",(OP_NONE
)}, /* FP condition code field */
234 {'r', 6, 5,"int", "destreg", (OP_NONE
)}, /* FP fd register */
235 {'s',21, 5,"t_reg", "op1", (OP_GPR
)}, /* integer source/rs register */
236 {'t',16, 5,"int", "destreg", (OP_NONE
)}, /* integer target rt (destination) register */
237 {'u', 0, 4,"int", "cmpflags", (OP_NONE
)}, /* FP comparison control flags */
238 {'v',11, 5,"int", "fs", (OP_NONE
)}, /* FP fs register (or PREFX hint) */
239 {'w', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset (lo-2bits must be zero) */
240 {'x',23, 1,"int", "to", (OP_NONE
)}, /* TRUE if move To; FALSE if move From */
241 {'y', 0,16,"t_reg", "offset", (OP_SIGNX
)}, /* signed offset */
242 {'z', 0,16,"ut_reg","op2", (OP_NONE
)}, /* unsigned immediate (zero extended) */
245 /* Main instruction encoding types: */
252 COP1S
, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
254 /* mips16 encoding types. */
255 I
, RI
, RR
, RRI
, RRR
, RRI_A
, ISHIFT
, I8
, I8_MOVR32
, I8_MOV32R
, I64
, RI64
258 /* Main instruction families: */
260 ADD
, /* res = operand1 + operand2 */
261 SUB
, /* res = operand1 - operand2 */
262 MUL
, /* res = operand1 * operand2 */
263 DIV
, /* res = operand1 / operand2 */
264 AND
, /* res = operand1 & operand2 */
265 OR
, /* res = operand1 | operand2 */
266 XOR
, /* res = operand1 ^ operand2 */
267 MOVE
, /* res = operand1 */
268 BRANCH
, /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
269 JUMP
, /* execute delay slot instruction before jump */
270 LOAD
, /* load from memory */
271 STORE
, /* store to memory */
272 PREFETCH
, /* prefetch data into cache */
273 SET
, /* set register on result of condition code */
274 SHIFT
, /* perform a logical or arithmetic shift */
275 TRAP
, /* system exception generation */
276 BREAK
, /* system breakpoint exception generation */
277 SYSCALL
, /* system exception generation */
278 SYNC
, /* system cache control */
279 DECODE
, /* co-processor instruction */
280 CACHE
, /* co-processor 0 CACHE instruction */
281 MADD16
, /* VR4100 specific multiply-add extensions */
299 RSVD
/* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
303 #define NONE (0 << 0) /* Zero value (used to keep source tidy) */
304 #define SIM_SH_SIZE (0)
305 #define SIM_MASK_SIZE (0x7)
306 #define BYTE (0) /* 8bit */
307 #define HALFWORD (1) /* 16bit */
308 #define WORD (2) /* 32bit */
309 #define DOUBLEWORD (3) /* 64bit */
310 #define SINGLE (4) /* single precision FP */
311 #define DOUBLE (5) /* double precision FP */
313 /* Shorthand to get the size field from the flags value: */
314 #define GETDATASIZE() ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
315 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
317 /* The rest are single bit flags: */
318 #define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
323 #define LIKELY (1 << 8)
324 #define SIGNEXTEND (1 << 9)
325 #define OVERFLOW (1 << 10)
326 #define LINK (1 << 11)
327 #define ATOMIC (1 << 12)
328 #define SHIFT16 (1 << 13)
329 #define REG (1 << 14)
330 #define LEFT (1 << 15) /* Deliberate explicit encodings to allow check for neither, or both */
331 #define RIGHT (1 << 16) /* Mutually exclusive with "LEFT" */
332 #define LOGICAL (1 << 17)
333 #define ARITHMETIC (1 << 18)
334 #define UNSIGNED (1 << 19)
335 #define HI32 (1 << 20)
336 #define HI (1 << 21) /* accesses or updates the HI register */
337 #define LO (1 << 22) /* accesses or updates the LO register */
338 #define WORD32 (1 << 23)
339 #define FP (1 << 24) /* Floating Point operation */
340 #define FIXED (1 << 25) /* fixed point arithmetic */
341 #define COPROC (1 << 26)
342 #define INTEGER (1 << 27)
343 #define CONDITIONAL (1 << 28)
344 #define RECIP (1 << 29)
345 #define CONTROL (1 << 30)
346 #define NOARG (1 << 31) /* Instruction has no (defined) operands */
347 /* NOTE: We can overload the use of certain of these flags, since not
348 all options are applicable to all instruction types. This will free
349 up more space for new flags. */
351 typedef struct instruction
{
352 char *name
; /* ASCII mnemonic name */
353 unsigned int isa
; /* MIPS ISA number where instruction introduced */
354 char *bitmap
; /* 32character string describing instruction operands */
355 inst_type mark
; /* type of MIPS instruction encoding */
356 opcode_type type
; /* main instruction family */
357 unsigned int flags
; /* flags describing instruction features */
359 /* The number of pipeline cycles taken by an instruction varies
360 between MIPS processors. This means that the information must be
361 encoded elsewhere, in a CPU specific structure. */
363 /* NOTE: Undefined instructions cause "Reserved Instruction"
364 exceptions. i.e. if there is no bit-mapping defined then the
365 instruction is deemed to be undefined. */
367 /* NOTE: The "isa" field is also used to encode flags for particular
368 chip architecture extensions. e.g. the NEC VR4100 specific
369 instructions. Normally chip extensions are added via the COP0
370 space. However, the VR4100 (and possibly other devices) also use
371 the normal instruction space. */
372 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
373 /* The other bits are allocated downwards, to avoid renumbering if we
374 have to extend the bits allocated to the pure ISA number. */
375 #define ARCH_VR4100 ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
377 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
378 COP0 space. This means that an external decoder should be added
379 when constructing a full VR4100 simulator. However some arithmetic
380 instructions are encoded in the normal instruction space. */
382 struct instruction MIPS_DECODE
[] = {
383 /* The instructions are alphabetical, and not in instruction bit-order: */
384 {"ABS", 1,"01000110mmm00000vvvvvrrrrr000101",COP1
, FPABS
, (FP
)},
385 {"ADD", 1,"000000sssssgggggddddd00000100000",SPECIAL
,ADD
, (WORD
| WORD32
| OVERFLOW
)}, /* rd = rs + rt */
386 {"ADD", 1,"01000110mmmkkkkkvvvvvrrrrr000000",COP1
, FPADD
, (FP
)},
387 {"ADDI", 1,"001000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
| OVERFLOW
)},
388 {"ADDU", 1,"000000sssssgggggddddd00000100001",SPECIAL
,ADD
, (WORD
| WORD32
)}, /* rd = rs + rt */
389 {"ADDIU", 1,"001001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (WORD
| WORD32
)},
390 {"AND", 1,"000000sssssgggggddddd00000100100",SPECIAL
,AND
, (NONE
)}, /* rd = rs AND rt */
391 {"ANDI", 1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, AND
, (NONE
)},
392 {"BC1", 1,"01000101000qqqfcllllllllllllllll",COP1S
, BRANCH
, (FP
)},
393 {"BEQ", 1,"000100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
)},
394 {"BEQL", 2,"010100sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (EQ
| LIKELY
)},
395 {"BGEZ", 1,"000001sssss00001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
)},
396 {"BGEZAL", 1,"000001sssss10001llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
397 {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LINK
)},
398 {"BGEZL", 2,"000001sssss00011llllllllllllllll",REGIMM
, BRANCH
, (GT
| EQ
| LIKELY
)},
399 {"BGTZ", 1,"000111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
)},
400 {"BGTZL", 2,"010111sssss00000llllllllllllllll",NORMAL
, BRANCH
, (GT
| LIKELY
)},
401 {"BLEZ", 1,"000110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
)},
402 {"BLEZL", 2,"010110sssss00000llllllllllllllll",NORMAL
, BRANCH
, (LT
| EQ
| LIKELY
)},
403 {"BLTZ", 1,"000001sssss00000llllllllllllllll",REGIMM
, BRANCH
, (LT
)},
404 {"BLTZAL", 1,"000001sssss10000llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
)},
405 {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LINK
| LIKELY
)},
406 {"BLTZL", 2,"000001sssss00010llllllllllllllll",REGIMM
, BRANCH
, (LT
| LIKELY
)},
407 {"BNE", 1,"000101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
)},
408 {"BNEL", 2,"010101sssssgggggllllllllllllllll",NORMAL
, BRANCH
, (NOT
| EQ
| LIKELY
)},
409 {"BREAK", 1,"000000????????????????????001101",SPECIAL
,BREAK
, (NOARG
)},
410 {"CEIL.L", 3,"01000110mmm00000vvvvvrrrrr001010",COP1
, FPCEIL
, (FP
| FIXED
| DOUBLEWORD
)},
411 {"CEIL.W", 2,"01000110mmm00000vvvvvrrrrr001110",COP1
, FPCEIL
, (FP
| FIXED
| WORD
)},
412 {"COP0", 1,"010000??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
413 {"COP2", 1,"010010??????????????????????????",NORMAL
, DECODE
, (NOARG
)},
414 {"CVT.D", 1,"01000110mmm00000vvvvvrrrrr100001",COP1
, FPCONVERT
,(FP
| DOUBLE
)},
415 {"CVT.L", 3,"01000110mmm00000vvvvvrrrrr100101",COP1
, FPCONVERT
,(FP
| FIXED
| DOUBLEWORD
)},
416 {"CVT.S", 1,"01000110mmm00000vvvvvrrrrr100000",COP1
, FPCONVERT
,(FP
| SINGLE
)},
417 {"CVT.W", 1,"01000110mmm00000vvvvvrrrrr100100",COP1
, FPCONVERT
,(FP
| FIXED
| WORD
)},
418 {"C.%s", 1,"01000110mmmkkkkkvvvvvppp0011uuuu",COP1
, FPCOMPARE
,(FP
)},
419 {"CxC1", 1,"01000100x10kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
| CONTROL
)},
420 {"DADD", 3,"000000sssssgggggddddd00000101100",SPECIAL
,ADD
, (DOUBLEWORD
| OVERFLOW
)},
421 {"DADDI", 3,"011000ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| OVERFLOW
)},
422 {"DADDU", 3,"000000sssssgggggddddd00000101101",SPECIAL
,ADD
, (DOUBLEWORD
| UNSIGNED
)},
423 {"DADDIU", 3,"011001ssssstttttiiiiiiiiiiiiiiii",NORMAL
, ADD
, (DOUBLEWORD
| UNSIGNED
)},
424 {"DDIV", 3,"000000sssssggggg0000000000011110",SPECIAL
,DIV
, (DOUBLEWORD
| HI
| LO
)},
425 {"DDIVU", 3,"000000sssssggggg0000000000011111",SPECIAL
,DIV
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
426 {"DIV", 1,"000000sssssggggg0000000000011010",SPECIAL
,DIV
, (WORD
| WORD32
| SIGNEXTEND
| HI
| LO
)},
427 {"DIV", 1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1
, FPDIV
, (FP
| WORD
| HI
| LO
)},
428 {"DIVU", 1,"000000sssssggggg0000000000011011",SPECIAL
,DIV
, (WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
)},
429 {"DMADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101001",SPECIAL
,MADD16
, (DOUBLEWORD
| HI
| LO
)},
430 {"DMULT", 3,"000000sssssggggg0000000000011100",SPECIAL
,MUL
, (DOUBLEWORD
| HI
| LO
)},
431 {"DMULTU", 3,"000000sssssggggg0000000000011101",SPECIAL
,MUL
, (DOUBLEWORD
| UNSIGNED
| HI
| LO
)},
432 {"DMxC1", 3,"01000100x01kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| DOUBLEWORD
)},
433 {"DSLL", 3,"00000000000gggggdddddaaaaa111000",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
)},
434 {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| REG
)},
435 {"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL
,SHIFT
, (DOUBLEWORD
| LEFT
| LOGICAL
| HI32
)}, /* rd = rt << (sa + 32) */
436 {"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
)},
437 {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
)},
438 {"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| ARITHMETIC
| HI32
)}, /* rd = rt >> (sa + 32) */
439 {"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
)},
440 {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| REG
)},
441 {"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL
,SHIFT
, (DOUBLEWORD
| RIGHT
| LOGICAL
| HI32
)},
442 {"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL
,SUB
, (DOUBLEWORD
)},
443 {"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL
,SUB
, (DOUBLEWORD
| UNSIGNED
)},
444 {"FLOOR.L", 3,"01000110mmm00000vvvvvrrrrr001011",COP1
, FPFLOOR
, (FP
| FIXED
| DOUBLEWORD
)},
445 {"FLOOR.W", 2,"01000110mmm00000vvvvvrrrrr001111",COP1
, FPFLOOR
, (FP
| FIXED
| WORD
)},
446 {"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (NONE
)}, /* NOTE: boundary case due to delay slot address being used */
447 {"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
)}, /* NOTE: boundary case due to delay slot address being used */
448 {"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL
,JUMP
, (LINK
| REG
)},
449 {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL
, JUMP
, (LINK
| NOT
)},
450 {"JR", 1,"000000sssss000000000000000001000",SPECIAL
,JUMP
, (NONE
)}, /* need to check PC as part of instruction fetch */
451 {"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
| SIGNEXTEND
)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
452 {"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (BYTE
)}, /* NOTE: See "LB" comment */
453 {"LD", 3,"110111sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
)},
454 {"LDC1", 2,"110101sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
455 {"LDC2", 2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| COPROC
)},
456 {"LDL", 3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| LEFT
)}, /* NOTE: See "LB" comment */
457 {"LDR", 3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (DOUBLEWORD
| RIGHT
)}, /* NOTE: See "LB" comment */
458 {"LDXC1", 4,"010011sssssggggg00000rrrrr000001",COP1X
, LOAD
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
459 {"LH", 1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
| SIGNEXTEND
)},
460 {"LHU", 1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL
, LOAD
, (HALFWORD
)},
461 {"LL", 2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| ATOMIC
| SIGNEXTEND
)},
462 {"LLD", 3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL
, LOAD
, (DOUBLEWORD
| ATOMIC
)},
463 {"LUI", 1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL
, MOVE
, (SHIFT16
)}, /* Cheat and specify sign-extension of immediate field */
464 {"LW", 1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| SIGNEXTEND
)},
465 {"LWC1", 1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
466 {"LWC2", 1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
| COPROC
)},
467 {"LWL", 1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| LEFT
)},
468 {"LWR", 1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL
, LOAD
, (WORD
| RIGHT
)},
469 {"LWU", 3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL
, LOAD
, (WORD
)},
470 {"LWXC1", 4,"010011sssssggggg00000rrrrr000000",COP1X
, LOAD
, (FP
| WORD
| COPROC
| REG
)},
471 {"MADD16", (ARCH_VR4100
| 3),"000000sssssggggg0000000000101000",SPECIAL
,MADD16
, (WORD
| HI
| LO
)},
472 {"MADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X
, FPADD
, (FP
| MULTIPLY
| DOUBLE
)},
473 {"MADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X
, FPADD
, (FP
| MULTIPLY
| SINGLE
)},
474 {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL
,MOVE
, (HI
| LEFT
)}, /* with following, from and to denoted by usage of LEFT or RIGHT */
475 {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL
,MOVE
, (LO
| LEFT
)},
476 {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL
,MOVE
, (HI
| RIGHT
)},
477 {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL
,MOVE
, (LO
| RIGHT
)},
478 {"MOV", 1,"01000110mmm00000vvvvvrrrrr000110",COP1
, FPMOVE
, (FP
)},
479 {"MOVN", 4,"000000sssssgggggddddd00000001011",SPECIAL
,MOVE
, (NOT
| EQ
)},
480 {"MOVN", 4,"01000110mmmgggggvvvvvrrrrr010011",COP1
, FPMOVE
, (FP
| NOT
| EQ
)},
481 {"MOV%c", 4,"000000sssssqqq0cddddd00000000001",SPECIAL
,FPMOVE
, (FP
| CONDITIONAL
| INTEGER
)},
482 {"MOV%c", 4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1
, FPMOVE
, (FP
| CONDITIONAL
)},
483 {"MOVZ", 4,"000000sssssgggggddddd00000001010",SPECIAL
,MOVE
, (EQ
)},
484 {"MOVZ", 4,"01000110mmmgggggvvvvvrrrrr010010",COP1
, FPMOVE
, (FP
| EQ
)},
485 {"MSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X
, FPSUB
, (FP
| MULTIPLY
| DOUBLE
)},
486 {"MSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X
, FPSUB
, (FP
| MULTIPLY
| SINGLE
)},
487 {"MUL", 1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1
, FPMUL
, (FP
| HI
| LO
)},
488 {"MULT", 1,"000000sssssggggg0000000000011000",SPECIAL
,MUL
, (WORD
| WORD32
| HI
| LO
)},
489 {"MULTU", 1,"000000sssssggggg0000000000011001",SPECIAL
,MUL
, (WORD
| WORD32
| UNSIGNED
| HI
| LO
)},
490 {"MxC1", 1,"01000100x00kkkkkvvvvv00000000000",COP1S
, FPMOVEC
, (FP
| WORD
)},
491 {"NEG", 1,"01000110mmm00000vvvvvrrrrr000111",COP1
, FPNEG
, (FP
)},
492 {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
493 {"NMADD.S", 4,"010011bbbbbkkkkkvvvvvrrrrr110000",COP1X
, FPADD
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
494 {"NMSUB.D", 4,"010011bbbbbkkkkkvvvvvrrrrr111001",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| DOUBLE
)},
495 {"NMSUB.S", 4,"010011bbbbbkkkkkvvvvvrrrrr111000",COP1X
, FPSUB
, (FP
| NOT
| MULTIPLY
| SINGLE
)},
496 {"NOR", 1,"000000sssssgggggddddd00000100111",SPECIAL
,OR
, (NOT
)},
497 {"OR", 1,"000000sssssgggggddddd00000100101",SPECIAL
,OR
, (NONE
)},
498 {"ORI", 1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, OR
, (NONE
)},
499 {"PREF", 4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, PREFETCH
, (NONE
)},
500 {"PREFX", 4,"010011sssssgggggvvvvv00000001111",COP1X
, FPPREFX
, (FP
)},
501 {"RECIP", 4,"01000110mmm00000vvvvvrrrrr010101",COP1
, FPRECIP
, (FP
)},
502 {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1
, FPROUND
, (FP
| FIXED
| DOUBLEWORD
)},
503 {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1
, FPROUND
, (FP
| FIXED
| WORD
)},
504 {"RSQRT", 4,"01000110mmm00000vvvvvrrrrr010110",COP1
, FPSQRT
, (FP
| RECIP
)},
505 {"SB", 1,"101000sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (BYTE
)},
506 {"SC", 2,"111000sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| ATOMIC
)},
507 {"SCD", 3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| ATOMIC
)},
508 {"SD", 3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
)},
509 {"SDC1", 2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
510 {"SDC2", 2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL
, STORE
, (DOUBLEWORD
| COPROC
)},
511 {"SDL", 3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| LEFT
)},
512 {"SDR", 3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (DOUBLEWORD
| RIGHT
)},
513 {"SDXC1", 4,"010011sssssgggggvvvvv00000001001",COP1X
, STORE
, (FP
| DOUBLEWORD
| COPROC
| REG
)},
514 {"SH", 1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL
, STORE
, (HALFWORD
)},
515 {"SLL", 1,"00000000000gggggdddddaaaaa000000",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << sa */
516 {"SLLV", 1,"000000ooooogggggddddd00000000100",SPECIAL
,SHIFT
, (WORD
| LEFT
| LOGICAL
)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
517 {"SLT", 1,"000000sssssgggggddddd00000101010",SPECIAL
,SET
, (LT
)},
518 {"SLTI", 1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
)},
519 {"SLTU", 1,"000000sssssgggggddddd00000101011",SPECIAL
,SET
, (LT
| UNSIGNED
)},
520 {"SLTIU", 1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL
, SET
, (LT
| UNSIGNED
)},
521 {"SQRT", 2,"01000110mmm00000vvvvvrrrrr000100",COP1
, FPSQRT
, (FP
)},
522 {"SRA", 1,"00000000000gggggdddddaaaaa000011",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
523 {"SRAV", 1,"000000ooooogggggddddd00000000111",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| ARITHMETIC
)},
524 {"SRL", 1,"00000000000gggggdddddaaaaa000010",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
525 {"SRLV", 1,"000000ooooogggggddddd00000000110",SPECIAL
,SHIFT
, (WORD
| WORD32
| RIGHT
| LOGICAL
)},
526 {"SUB", 1,"000000sssssgggggddddd00000100010",SPECIAL
,SUB
, (WORD
| WORD32
| OVERFLOW
)},
527 {"SUB", 1,"01000110mmmkkkkkvvvvvrrrrr000001",COP1
, FPSUB
, (FP
)},
528 {"SUBU", 1,"000000sssssgggggddddd00000100011",SPECIAL
,SUB
, (WORD
| WORD32
)},
529 {"SW", 1,"101011sssssgggggwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
)},
530 {"SWC1", 1,"111001ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
531 {"SWC2", 1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL
, STORE
, (WORD
| COPROC
)},
532 {"SWL", 1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| LEFT
)},
533 {"SWR", 1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, STORE
, (WORD
| RIGHT
)},
534 {"SWXC1", 4,"010011sssssgggggvvvvv00000001000",COP1X
, STORE
, (FP
| WORD
| COPROC
| REG
)},
535 {"SYNC", 2,"000000000000000000000aaaaa001111",SPECIAL
,SYNC
, (NONE
)}, /* z = 5bit stype field */
536 {"SYSCALL", 1,"000000????????????????????001100",SPECIAL
,SYSCALL
, (NOARG
)},
537 {"TEQ", 2,"000000sssssggggg??????????110100",SPECIAL
,TRAP
, (EQ
)},
538 {"TEQI", 2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (EQ
)},
539 {"TGE", 2,"000000sssssggggg??????????110000",SPECIAL
,TRAP
, (GT
| EQ
)},
540 {"TGEI", 2,"000001sssss01000iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
)},
541 {"TGEIU", 2,"000001sssss01001iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (GT
| EQ
| UNSIGNED
)},
542 {"TGEU", 2,"000000sssssggggg??????????110001",SPECIAL
,TRAP
, (GT
| EQ
| UNSIGNED
)},
543 {"TLT", 2,"000000sssssggggg??????????110010",SPECIAL
,TRAP
, (LT
)},
544 {"TLTI", 2,"000001sssss01010iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
)},
545 {"TLTIU", 2,"000001sssss01011iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (LT
| UNSIGNED
)},
546 {"TLTU", 2,"000000sssssggggg??????????110011",SPECIAL
,TRAP
, (LT
| UNSIGNED
)},
547 {"TNE", 2,"000000sssssggggg??????????110110",SPECIAL
,TRAP
, (NOT
| EQ
)},
548 {"TNEI", 2,"000001sssss01110iiiiiiiiiiiiiiii",REGIMM
, TRAP
, (NOT
| EQ
)},
549 {"TRUNC.L", 3,"01000110mmm00000vvvvvrrrrr001001",COP1
, FPTRUNC
, (FP
| FIXED
| DOUBLEWORD
)},
550 {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1
, FPTRUNC
, (FP
| FIXED
| WORD
)},
551 {"XOR", 1,"000000sssssgggggddddd00000100110",SPECIAL
,XOR
, (NONE
)},
552 {"XORI", 1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL
, XOR
, (NONE
)},
553 {"CACHE", 3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL
, CACHE
, (NONE
)},
554 {"<INT>", 1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL
, RSVD
, (NONE
)},
557 static const struct instruction MIPS16_DECODE
[] = {
558 {"ADDIU", 1, "01000xxxddd04444", RRI_A
, ADD
, WORD
| WORD32
},
559 {"ADDIU8", 1, "01001wwwkkkkkkkk", RI
, ADD
, WORD
| WORD32
},
560 {"ADJSP", 1, "01100011KKKKKKKKS", I8
, ADD
, WORD
| WORD32
},
561 {"ADDIUPC", 1, "00001dddAAAAAAAAP", RI
, ADD
, WORD
| WORD32
},
562 {"ADDIUSP", 1, "00000dddAAAAAAAAs", RI
, ADD
, WORD
| WORD32
},
563 {"ADDU", 1, "11100xxxyyyddd01", RRR
, ADD
, WORD
| WORD32
},
564 {"AND", 1, "11101wwwyyy01100", RR
, AND
, NONE
},
565 {"B", 1, "00010qqqqqqqqqqqzZ", I
, BRANCH
, EQ
},
566 {"BEQZ", 1, "00100xxxppppppppz", RI
, BRANCH
, EQ
},
567 {"BNEZ", 1, "00101xxxppppppppz", RI
, BRANCH
, NOT
| EQ
},
568 {"BREAK", 1, "01100??????00101", RR
, BREAK
, NOARG
},
569 {"BTEQZ", 1, "01100000pppppppptz", I8
, BRANCH
, EQ
},
570 {"BTNEZ", 1, "01100001pppppppptz", I8
, BRANCH
, NOT
| EQ
},
571 {"CMP", 1, "11101xxxyyy01010T", RR
, XOR
, NONE
},
572 {"CMPI", 1, "01110xxxUUUUUUUUT", RI
, XOR
, NONE
},
573 {"DADDIU", 3, "01000xxxddd14444", RRI_A
, ADD
, DOUBLEWORD
},
574 {"DADDIU5", 3, "11111101wwwjjjjj", RI64
, ADD
, DOUBLEWORD
},
575 {"DADJSP", 3, "11111011KKKKKKKKS", I64
, ADD
, DOUBLEWORD
},
576 {"DADIUPC", 3, "11111110dddEEEEEP", RI64
, ADD
, DOUBLEWORD
},
577 {"DADIUSP", 3, "11111111dddEEEEEs", RI64
, ADD
, DOUBLEWORD
},
578 {"DADDU", 3, "11100xxxyyyddd00", RRR
, ADD
, DOUBLEWORD
},
579 {"DDIV", 3, "11101xxxyyy11110", RR
, DIV
, DOUBLEWORD
| HI
| LO
},
580 {"DDIVU", 3, "11101xxxyyy11111", RR
, DIV
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
581 {"DIV", 1, "11101xxxyyy11010", RR
, DIV
, WORD
| WORD32
| SIGNEXTEND
| HI
| LO
},
582 {"DIVU", 1, "11101xxxyyy11011", RR
, DIV
, WORD
| WORD32
| UNSIGNED
| SIGNEXTEND
| HI
| LO
},
583 {"DMULT", 3, "11101xxxyyy11100", RR
, MUL
, DOUBLEWORD
| HI
| LO
},
584 {"DMULTU", 3, "11101xxxyyy11101", RR
, MUL
, DOUBLEWORD
| UNSIGNED
| HI
| LO
},
585 {"DSLL", 3, "00110dddyyy[[[01", ISHIFT
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
},
586 {"DSLLV", 3, "11101xxxvvv10100", RR
, SHIFT
, DOUBLEWORD
| LEFT
| LOGICAL
| REG
},
587 {"DSRA", 3, "11101]]]vvv10011", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
},
588 {"DSRAV", 3, "11101xxxvvv10111", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| ARITHMETIC
| REG
},
589 {"DSRL", 3, "11101]]]vvv01000", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
},
590 {"DSRLV", 3, "11101xxxvvv10110", RR
, SHIFT
, DOUBLEWORD
| RIGHT
| LOGICAL
| REG
},
591 {"DSUBU", 3, "11100xxxyyyddd10", RRR
, SUB
, DOUBLEWORD
| UNSIGNED
},
593 /* FIXME: Should we handle these ourselves, or should we require an
594 emulation routine? */
595 {"EXIT", 1, "1110111100001000", RR
, BREAK
, EXIT
},
596 {"ENTRY", 1, "11101??????01000", RR
, BREAK
, ENTRY
},
598 {"EXTEND", 1, "11110eeeeeeeeeee", I
, RSVD
, NOARG
},
599 {"JALR", 1, "11101xxx01000000R", RR
, JUMP
, LINK
| REG
},
600 {"JAL", 1, "00011aaaaaaaaaaa", I
, JUMP
, LINK
},
601 {"JR", 1, "11101xxx00000000", RR
, JUMP
, NONE
},
602 {"JRRA", 1, "1110100000100000r", RR
, JUMP
, NONE
},
603 {"LB", 1, "10000xxxddd55555", RRI
, LOAD
, BYTE
| SIGNEXTEND
},
604 {"LBU", 1, "10100xxxddd55555", RRI
, LOAD
, BYTE
},
605 {"LD", 3, "00111xxxdddDDDDD", RRI
, LOAD
, DOUBLEWORD
},
606 {"LDPC", 3, "11111100dddDDDDDP", RI64
, LOAD
, DOUBLEWORD
},
607 {"LDSP", 3, "11111000dddDDDDDs", RI64
, LOAD
, DOUBLEWORD
},
608 {"LH", 1, "10001xxxdddHHHHH", RRI
, LOAD
, HALFWORD
| SIGNEXTEND
},
609 {"LHU", 1, "10101xxxdddHHHHH", RRI
, LOAD
, HALFWORD
},
610 {"LI", 1, "01101dddUUUUUUUUZ", RI
, OR
, NONE
},
611 {"LW", 1, "10011xxxdddWWWWW", RRI
, LOAD
, WORD
| SIGNEXTEND
},
612 {"LWPC", 1, "10110dddVVVVVVVVP", RI
, LOAD
, WORD
| SIGNEXTEND
},
613 {"LWSP", 1, "10010dddVVVVVVVVs", RI
, LOAD
, WORD
| SIGNEXTEND
},
614 {"LWU", 1, "10111xxxdddWWWWW", RRI
, LOAD
, WORD
},
615 {"MFHI", 1, "11101ddd00010000", RR
, MOVE
, HI
| LEFT
},
616 {"MFLO", 1, "11101ddd00010010", RR
, MOVE
, LO
| LEFT
},
617 {"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32
, OR
, NONE
},
618 {"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R
, OR
, NONE
},
619 {"MULT", 1, "11101xxxyyy11000", RR
, MUL
, WORD
| WORD32
| HI
| LO
},
620 {"MULTU", 1, "11101xxxyyy11001", RR
, MUL
, WORD
| WORD32
| UNSIGNED
| HI
| LO
},
621 {"NEG", 1, "11101dddyyy01011Z", RR
, SUB
, WORD
},
622 {"NOT", 1, "11101dddyyy01111Z", RR
, OR
, NOT
},
623 {"OR", 1, "11101wwwyyy01101", RR
, OR
, NONE
},
624 {"SB", 1, "11000xxxyyy55555", RRI
, STORE
, BYTE
},
625 {"SD", 3, "01111xxxyyyDDDDD", RRI
, STORE
, DOUBLEWORD
},
626 {"SDSP", 3, "11111001yyyDDDDDs", RI64
, STORE
, DOUBLEWORD
},
627 {"SDRASP", 3, "11111010CCCCCCCCsQ", I64
, STORE
, DOUBLEWORD
},
628 {"SH", 1, "11001xxxyyyHHHHH", RRI
, STORE
, HALFWORD
},
629 {"SLL", 1, "00110dddyyy<<<00", ISHIFT
, SHIFT
, WORD
| LEFT
| LOGICAL
},
630 {"SLLV", 1, "11101xxxvvv00100", RR
, SHIFT
, WORD
| LEFT
| LOGICAL
| REG
},
631 {"SLT", 1, "11101xxxyyy00010T", RR
, SET
, LT
},
632 {"SLTI", 1, "01010xxx88888888T", RI
, SET
, LT
},
633 {"SLTU", 1, "11101xxxyyy00011T", RR
, SET
, LT
| UNSIGNED
},
634 {"SLTIU", 1, "01011xxx88888888T", RI
, SET
, LT
| UNSIGNED
},
635 {"SRA", 1, "00110dddyyy<<<11", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
},
636 {"SRAV", 1, "11101xxxvvv00111", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| ARITHMETIC
| REG
},
637 {"SRL", 1, "00110dddyyy<<<10", ISHIFT
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
},
638 {"SRLV", 1, "11101xxxvvv00110", RR
, SHIFT
, WORD
| WORD32
| RIGHT
| LOGICAL
| REG
},
639 {"SUBU", 1, "11100xxxyyyddd11", RRR
, SUB
, WORD
| WORD32
},
640 {"SW", 1, "11011xxxyyyWWWWW", RRI
, STORE
, WORD
},
641 {"SWSP", 1, "11010yyyVVVVVVVVs", RI
, STORE
, WORD
},
642 {"SWRASP", 1, "01100010VVVVVVVVQs", I8
, STORE
, WORD
},
643 {"XOR", 1, "11101wwwyyy01110", RR
, XOR
, NONE
}
646 static int bitmap_val
PARAMS ((const char *, int, int));
647 static void build_mips16_operands
PARAMS ((const char *));
648 static void build_instruction
649 PARAMS ((int, unsigned int, int, const struct instruction
*));
651 /*---------------------------------------------------------------------------*/
653 /* We use the letter ordinal as the bit-position in our flags field: */
654 #define fieldval(l) (1 << ((l) - 'a'))
657 convert_bitmap(bitmap
,onemask
,zeromask
,dontmask
)
659 unsigned int *onemask
, *zeromask
, *dontmask
;
661 unsigned int flags
= 0x00000000;
662 int loop
; /* current bitmap position */
663 int lastsp
= -1; /* last bitmap field starting position */
664 int lastoe
= -1; /* last bitmap field encoding */
666 *onemask
= 0x00000000;
667 *zeromask
= 0x00000000;
668 *dontmask
= 0x00000000;
670 if (strlen(bitmap
) != 32) {
671 fprintf(stderr
,"Invalid bitmap string - not 32 characters long \"%s\"\n",bitmap
);
675 for (loop
= 0; (loop
< 32); loop
++) {
677 for (oefield
= 0; (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))); oefield
++)
678 if (bitmap
[31 - loop
] == opfields
[oefield
].id
)
680 if (oefield
< (sizeof(opfields
) / sizeof(struct operand_encoding
))) {
681 if ((lastoe
!= -1) && (lastoe
!= oefield
))
682 if ((loop
- lastsp
) != (opfields
[lastoe
].flen
)) {
683 fprintf(stderr
,"Invalid field length %d for bitmap field '%c' (0x%02X) (should be %d) : bitmap = \"%s\"\n",(loop
- lastsp
),(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],opfields
[lastoe
].flen
,bitmap
);
687 switch (bitmap
[31 - loop
]) {
688 case '0' : /* fixed value */
689 *zeromask
|= (1 << loop
);
694 case '1' : /* fixed value */
695 *onemask
|= (1 << loop
);
700 case '?' : /* fixed value */
701 *dontmask
|= (1 << loop
);
706 default : /* check character encoding */
708 if (opfields
[oefield
].fpos
!= -1) {
709 /* If flag not set, then check starting position: */
710 if (!(flags
& fieldval(bitmap
[31 - loop
]))) {
711 if (loop
!= opfields
[oefield
].fpos
) {
712 fprintf(stderr
,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],loop
,bitmap
);
715 flags
|= fieldval(bitmap
[31 - loop
]);
720 *dontmask
|= (1 << loop
);
725 fprintf(stderr
,"Unrecognised bitmap character '%c' (0x%02X) at offset %d in bitmap \"%s\"\n",(((bitmap
[31 - loop
] < 0x20) || (bitmap
[31 - loop
] >= 0x7F)) ? '.' : bitmap
[31 - loop
]),bitmap
[31 - loop
],loop
,bitmap
);
730 /* NOTE: Since we check for the position and size of fields when
731 parsing the "bitmap" above, we do *NOT* need to check that invalid
732 field combinations have been used. */
737 /* Get the value of a 16 bit bitstring for a given shift count and
741 bitmap_val (bitmap
, shift
, bits
)
750 s
= bitmap
+ 16 - shift
- bits
;
751 for (; bits
> 0; --bits
)
766 /*---------------------------------------------------------------------------*/
769 build_operands(flags
)
773 for (loop
= 0; (loop
< (sizeof(opfields
) / sizeof(operand_encoding
))); loop
++)
774 if ((opfields
[loop
].fpos
!= -1) && (flags
& fieldval(opfields
[loop
].id
))) {
775 printf(" %s %s = ",opfields
[loop
].type
,opfields
[loop
].name
);
777 if (opfields
[loop
].flags
& OP_SIGNX
)
778 printf("SIGNEXTEND((%s)",opfields
[loop
].type
);
780 if (opfields
[loop
].flags
& OP_GPR
)
783 if (opfields
[loop
].flags
& OP_SHIFT2
)
786 printf("((instruction >> %d) & 0x%08X)",opfields
[loop
].fpos
,((1 << opfields
[loop
].flen
) - 1));
788 if (opfields
[loop
].flags
& OP_SHIFT2
)
791 if (opfields
[loop
].flags
& OP_GPR
)
794 if (opfields
[loop
].flags
& OP_BITS5
)
797 if (opfields
[loop
].flags
& OP_SIGNX
)
798 printf(",%d)",(opfields
[loop
].flen
+ ((opfields
[loop
].flags
& OP_SHIFT2
) ? 2 : 0)));
806 /* The mips16 operand table. */
810 /* The character which appears in the bitmap string. */
812 /* The type of the variable in the simulator. */
814 /* The name of the variable in the simulator. */
816 /* The number of bits. */
818 /* The number of bits when extended (zero if can not be extended). */
820 /* The amount by which the short form is shifted when it is used;
821 for example, the sw instruction has a shift count of 2. */
827 /* Flags which appears in the mips16 operand table. */
829 /* Whether this is a mips16 register index. */
830 #define MIPS16_REG16 (0x1)
831 /* Whether this is a register value. */
832 #define MIPS16_REGVAL (0x2)
833 /* Whether this is a swapped mips32 register index (MOV32R) */
834 #define MIPS16_REG32_SWAPPED (0x4)
835 /* Whether this index is also the destination register. */
836 #define MIPS16_DESTREG (0x8)
837 /* Whether the short form is unsigned. */
838 #define MIPS16_UNSP (0x10)
839 /* Whether the extended form is unsigned. */
840 #define MIPS16_EXTU (0x20)
841 /* Implicit stack pointer. */
842 #define MIPS16_SP (0x40)
843 /* Implicit program counter. */
844 #define MIPS16_PC (0x80)
846 #define MIPS16_ZERO (0x100)
848 #define MIPS16_TREG (0x200)
850 #define MIPS16_RA (0x400)
852 #define MIPS16_JUMP_ADDR (0x800)
854 #define MIPS16_BRANCH (0x1000)
856 /* The mips16 operand table. */
858 static const struct mips16_op mips16_op_table
[] =
860 { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16
},
861 { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
862 { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
863 { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
| MIPS16_REGVAL
},
864 { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16
|MIPS16_REGVAL
|MIPS16_DESTREG
},
865 { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL
},
866 { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED
},
867 { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR
},
868 { 'e', "int", "ext", 11, 0, 0, 0 },
869 { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
870 { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP
| MIPS16_EXTU
},
871 { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
872 { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP
| MIPS16_EXTU
},
873 { '4', "int", "op2", 4, 15, 0, 0 },
874 { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP
},
875 { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP
},
876 { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP
},
877 { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP
},
878 { 'j', "int", "op2", 5, 16, 0, 0 },
879 { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP
},
880 { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP
},
881 { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP
},
882 { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP
| MIPS16_EXTU
},
883 { 'k', "int", "op2", 8, 16, 0, 0 },
884 { 'K', "int", "op2", 8, 16, 3, 0 },
885 { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH
},
886 { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH
},
887 { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP
},
888 { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP
},
889 { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP
},
891 /* The remaining operands are special operands which encode implied
892 arguments. These only appear at the end of a bitmap string, and
893 do not represent actual bits. */
894 { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP
| MIPS16_REGVAL
},
895 { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP
|MIPS16_REGVAL
|MIPS16_DESTREG
},
896 { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC
},
897 { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO
},
898 { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO
},
899 { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG
| MIPS16_REGVAL
},
900 { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG
},
901 { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
902 { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA
},
903 { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA
| MIPS16_REGVAL
},
905 { '\0', NULL
, NULL
, 0, 0, 0, 0 }
908 /* Build mips16 operands. */
911 build_mips16_operands (bitmap
)
916 const struct mips16_op
*op
= NULL
;
917 const struct mips16_op
*ops
[3];
921 for (s
= bitmap
; *s
!= '\0'; s
++)
928 /* Make sure we saw the right number of bits for that
930 if (op
->nbits
!= 0 && (s
- bitmap
) - op
->nbits
!= start
)
935 if (*s
== '0' || *s
== '1' || *s
== '?')
940 for (op
= mips16_op_table
; op
->type
!= *s
; ++op
)
941 if (op
->type
== '\0')
944 printf (" %s %s = ", op
->vartype
, op
->name
);
946 printf ("(instruction >> %d) & 0x%x",
947 16 - (s
- bitmap
) - op
->nbits
,
948 (1 << op
->nbits
) - 1);
951 if ((op
->flags
& MIPS16_SP
) != 0)
953 else if ((op
->flags
& MIPS16_PC
) != 0)
957 printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? IPC - 4 : IPC - 2) : IPC) & ~ (uword64) 1)");
958 for (j
= 0; j
< opindex
; j
++)
959 if (ops
[j
]->shift
!= 0)
960 printf (" & ~ (uword64) 0x%x", (1 << ops
[j
]->shift
) - 1);
962 else if ((op
->flags
& MIPS16_ZERO
) != 0)
964 else if ((op
->flags
& MIPS16_TREG
) != 0)
966 else if ((op
->flags
& MIPS16_RA
) != 0)
973 if ((op
->flags
& MIPS16_DESTREG
) != 0)
974 printf (" int destreg;\n");
984 /* Make sure we saw the right number of bits for that
986 if (op
->nbits
!= 0 && 16 - op
->nbits
!= start
)
990 for (i
= 0; i
< opindex
; i
++)
993 if ((op
->flags
& MIPS16_REG16
) != 0)
995 printf (" if (%s < 2)\n", op
->name
);
996 printf (" %s += 16;\n", op
->name
);
998 if ((op
->flags
& MIPS16_REG32_SWAPPED
) != 0)
999 printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
1000 op
->name
, op
->name
, op
->name
);
1001 if ((op
->flags
& MIPS16_DESTREG
) != 0)
1002 printf (" destreg = %s;\n", op
->name
);
1003 if ((op
->flags
& MIPS16_REGVAL
) != 0)
1004 printf (" %s = GPR[%s];\n", op
->name
, op
->name
);
1006 if (op
->extbits
!= 0)
1008 printf (" if (have_extendval)\n");
1010 if (op
->extbits
== 16)
1011 printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
1013 else if (op
->extbits
== 15)
1014 printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
1016 else if (op
->extbits
== 6)
1017 printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
1020 printf (" %s = (extendval >> 6) & 0x1f;\n",
1022 if ((op
->flags
& MIPS16_EXTU
) == 0)
1024 printf (" if (%s >= 0x%x)\n",
1025 op
->name
, 1 << (op
->extbits
- 1));
1026 printf (" %s -= 0x%x;\n",
1027 op
->name
, 1 << op
->extbits
);
1029 printf (" have_extendval = 0;\n");
1033 if ((op
->flags
& MIPS16_UNSP
) == 0)
1035 printf (" if (%s >= 0x%x)\n",
1036 op
->name
, 1 << (op
->nbits
- 1));
1037 printf (" %s -= 0x%x;\n",
1038 op
->name
, 1 << op
->nbits
);
1041 printf (" %s <<= %d;\n", op
->name
, op
->shift
);
1042 if (op
->type
== '<' || op
->type
== '>'
1043 || op
->type
== '[' || op
->type
== ']')
1045 printf (" if (%s == 0)\n", op
->name
);
1046 printf (" %s = 8;\n", op
->name
);
1051 if ((op
->flags
& MIPS16_BRANCH
) != 0)
1052 printf (" %s *= 2;\n", op
->name
);
1054 if ((op
->flags
& MIPS16_JUMP_ADDR
) != 0)
1057 printf (" uword64 paddr;\n");
1058 printf (" int uncached;\n");
1059 printf (" if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
1061 printf (" uword64 memval;\n");
1062 printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
1063 printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
1064 printf (" unsigned int byte;\n");
1065 printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
1066 printf (" memval = LoadMemory (uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
1067 printf (" byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
1068 printf (" memval = (memval >> (8 * byte)) & 0xffff;\n");
1069 printf (" %s = (((%s & 0x1f) << 23)\n", op
->name
, op
->name
);
1070 printf (" | ((%s & 0x3e0) << 13)\n", op
->name
);
1071 printf (" | (memval << 2));\n");
1072 printf (" if ((instruction & 0x400) == 0)\n");
1073 printf (" %s |= 1;\n", op
->name
);
1074 printf (" PC += 2;\n");
1077 printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op
->name
);
1081 /* FIXME: Is this the way to detect an unused extend opcode? */
1082 printf (" if (have_extendval)\n");
1083 printf (" SignalException (ReservedInstruction, instruction);\n");
1086 /*---------------------------------------------------------------------------*/
1094 build_endian_shift(proc64
,datalen
,endbit
,direction
,shift
)
1098 e_endshift direction
;
1102 printf(" if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit
,endbit
);
1103 printf(" memval %s= %d;\n",direction
== s_left
? "<<" : ">>",shift
);
1110 /*---------------------------------------------------------------------------*/
1111 /* doisa = number of MIPS ISA simulator table is being constructed for.
1112 * proc64 = TRUE if constructing 64bit processor world.
1113 * dofp = boolean, TRUE if FP instructions are to be included.
1114 * fpsingle = boolean, TRUE if only single precision FP instructions to be included.
1118 process_instructions(doarch
,features
)
1119 unsigned int doarch
;
1120 unsigned int features
;
1122 int doisa
= (doarch
& MASK_ISA
);
1123 int limit
= (sizeof(MIPS_DECODE
) / sizeof(instruction
));
1124 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1125 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1126 int dofp
= (features
& FEATURE_HASFPU
);
1127 int fpsingle
= (features
& FEATURE_FPSINGLE
);
1132 fprintf(stderr
,"process_instructions: invalid structure length\n");
1136 if (proc64
&& (gprlen
!= 64)) {
1137 fprintf(stderr
,"Error: 64bit processor build specified, with MIPS ISA I or II\n");
1141 /* NOTE: "proc64" also differentiates between 32- and 64-bit wide memory */
1144 for (loop
= 0; (loop
< limit
); loop
++)
1145 if ((MIPS_DECODE
[loop
].isa
& MASK_ISA
) > maxisa
)
1146 maxisa
= (MIPS_DECODE
[loop
].isa
& MASK_ISA
);
1151 printf("#if defined(SIM_MANIFESTS)\n");
1152 printf("#define MIPSISA (%d)\n",doisa
);
1154 printf("#define PROCESSOR_64BIT (1 == 1)\n");
1156 printf("#define PROCESSOR_64BIT (1 == 0)\n");
1157 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
1158 printf("#define LOADDRMASK (0x%08X)\n",0x7);
1160 printf("#define LOADDRMASK (0x%08X)\n",(proc64
? 0x7 : 0x3));
1162 /* The FP registers are the same width as the CPU registers: */
1163 printf("#define GPRLEN (%d)\n",gprlen
);
1164 printf("typedef %s t_reg;\n",((gprlen
== 64) ? "word64" : "int"));
1165 printf("typedef %s ut_reg;\n",((gprlen
== 64) ? "uword64" : "unsigned int"));
1166 printf("typedef %s t_fpreg;\n",((gprlen
== 64) ? "word64" : "int"));
1168 printf("#define HASFPU (1 == 1)\n");
1169 if (features
& FEATURE_FAST
)
1170 printf("#define FASTSIM (1 == 1)\n");
1171 if (features
& FEATURE_WARN_STALL
)
1172 printf("#define WARN_STALL (1 == 1)\n");
1173 if (features
& FEATURE_WARN_LOHI
)
1174 printf("#define WARN_LOHI (1 == 1)\n");
1175 if (features
& FEATURE_WARN_ZERO
)
1176 printf("#define WARN_ZERO (1 == 1)\n");
1177 if (features
& FEATURE_WARN_MEM
)
1178 printf("#define WARN_MEM (1 == 1)\n");
1179 if (features
& FEATURE_WARN_R31
)
1180 printf("#define WARN_R31 (1 == 1)\n");
1181 if (features
& FEATURE_WARN_RESULT
)
1182 printf("#define WARN_RESULT (1 == 1)\n");
1184 printf("#else /* simulator engine */\n");
1186 printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
1187 printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64
? 64 : 32),doisa
,limit
);
1189 printf("/* %sFP instructions included */\n",(fpsingle
? "Single precision " : ""));
1190 printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
1193 printf("#if !defined(PROCESSOR_64BIT)\n");
1194 printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
1198 printf("/* Actual instruction decoding block */\n");
1199 printf("if ((vaddr & 1) == 0){\n");
1202 printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP
,OP_MASK_OP
);
1203 limit
= (OP_MASK_OP
+ 1);
1204 printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1205 limit
+= (OP_MASK_SPEC
+ 1);
1206 printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_RT
,OP_MASK_RT
);
1207 limit
+= (OP_MASK_RT
+ 1);
1208 printf("else if (num == 0x11) {\n");
1209 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM
,OP_SH_COP1NORM
,(OP_MASK_COP1NORM
<< OP_SH_COP1NORM
));
1210 printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP
,OP_SH_COP1CMP
,(OP_MASK_COP1CMP
<< OP_SH_COP1CMP
));
1211 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,(OP_MASK_SPEC
& (OP_MASK_COP1CMP
<< OP_SH_COP1CMP
)));
1213 printf(" num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1214 limit
+= (OP_MASK_SPEC
+ 1);
1216 /* To keep this code quick, we just clear out the "to" bit
1217 here. The proper (though slower) code would be to have another
1218 conditional, checking whether this instruction is a branch or
1219 not, before limiting the range to the bottom two bits of the
1221 printf(" num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit
,OP_SH_COP1SPEC
,OP_MASK_COP1SPEC
,OP_MASK_COP1SCLR
);
1222 limit
+= (OP_MASK_COP1SPEC
+ 1);
1223 printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit
,OP_SH_SPEC
,OP_MASK_SPEC
);
1224 limit
+= (OP_MASK_SPEC
+ 1);
1225 printf("/* Total possible switch entries: %d */\n",limit
) ;
1227 printf("switch (num)\n") ;
1230 for (loop
= 0; (loop
< limit
); loop
++) {
1231 /* First check that the ISA number we are constructing for is
1232 valid, before checking if the instruction matches any of the
1233 architecture specific flags. NOTE: We allow a selected ISA of
1234 zero to be used to match all standard instructions. */
1235 if ((((MIPS_DECODE
[loop
].isa
& MASK_ISA
) <= doisa
) && (((MIPS_DECODE
[loop
].isa
& ~MASK_ISA
) == 0) || ((MIPS_DECODE
[loop
].isa
& ~MASK_ISA
) & doarch
) != 0)) && (!(MIPS_DECODE
[loop
].flags
& FP
) || ((MIPS_DECODE
[loop
].flags
& FP
) && dofp
))) {
1236 unsigned int onemask
;
1237 unsigned int zeromask
;
1238 unsigned int dontmask
;
1240 unsigned int number
;
1241 unsigned int flags
= convert_bitmap(MIPS_DECODE
[loop
].bitmap
,&onemask
,&zeromask
,&dontmask
);
1243 if (!(MIPS_DECODE
[loop
].flags
& COPROC
) && ((GETDATASIZE() == DOUBLEWORD
) && !proc64
)) {
1244 fprintf(stderr
,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE
[loop
].name
);
1249 printf("/* DEBUG: onemask 0x%08X */\n",onemask
) ;
1250 printf("/* DEBUG: zeromask 0x%08X */\n",zeromask
) ;
1251 printf("/* DEBUG: dontmask 0x%08X */\n",dontmask
) ;
1254 switch (MIPS_DECODE
[loop
].mark
) {
1256 mask
= (OP_MASK_OP
<< OP_SH_OP
) ;
1257 number
= ((onemask
>> OP_SH_OP
) & OP_MASK_OP
) ;
1261 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1262 number
= ((OP_MASK_OP
+ 1) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1266 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_RT
<< OP_SH_RT
)) ;
1267 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_RT
) & OP_MASK_RT
)) ;
1271 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1272 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1276 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_COP1SPEC
<< OP_SH_COP1SPEC
)) ;
1277 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_COP1SPEC
) & OP_MASK_COP1SPEC
)) ;
1281 mask
= ((OP_MASK_OP
<< OP_SH_OP
) | (OP_MASK_SPEC
<< OP_SH_SPEC
)) ;
1282 number
= (((OP_MASK_OP
+ 1) + (OP_MASK_SPEC
+ 1) + (OP_MASK_RT
+ 1) + (OP_MASK_COP1SPEC
+ 1) + (OP_MASK_SPEC
+ 1)) + ((onemask
>> OP_SH_SPEC
) & OP_MASK_SPEC
)) ;
1286 fprintf(stderr
,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE
[loop
].mark
,loop
,MIPS_DECODE
[loop
].name
) ;
1290 printf("case %d : /* \"%s\" %s */\n",number
,MIPS_DECODE
[loop
].name
,MIPS_DECODE
[loop
].bitmap
) ;
1293 printf("/* DEBUG: mask 0x%08X */\n",mask
) ;
1294 printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE
[loop
].name
);
1297 /* Check if there are any other explicit bits in the instruction: */
1298 if ((~mask
& (onemask
| zeromask
)) != 0x00000000) {
1299 printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask
| zeromask
),onemask
) ;
1301 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1306 if ((flags
== 0) && !(MIPS_DECODE
[loop
].flags
& NOARG
)) {
1307 fprintf(stderr
,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE
[loop
].name
) ;
1313 /* Get hold of the operands */
1314 /* NOTE: If we wanted to make the simulator code smaller, we
1315 * could pull these into a common sequence before we perform
1316 * the instruction decoding. However, this would affect the
1317 * performance since unnecessary field extraction would be
1318 * occurring for certain instructions.
1320 * Also we do not perform checking for multiple definitions of a
1321 * particular operand here, since they are caught by the
1322 * compilation of the produced code.
1324 build_operands(flags
);
1326 /* Finish constructing the jump address if required: */
1327 if (flags
& fieldval('j'))
1328 printf(" op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
1330 /* Now perform required operand checks: */
1332 /* The following code has been removed, since it seems perfectly
1333 reasonable to have a non-aligned offset that is added to another
1334 non-aligned base to create an aligned address. Some more
1335 information on exactly what the MIPS IV specification requires is
1336 needed before deciding on the best strategy. Experimentation with a
1337 VR4300 suggests that we do not need to raise the warning. */
1339 /* For MIPS IV (and onwards), certain instruction operand values
1340 will give undefined results. For the simulator we could
1341 generate explicit exceptions (i.e. ReservedInstruction) to
1342 make it easier to spot invalid use. However, for the moment we
1343 just raise a warning. NOTE: This is a different check to the
1344 later decoding, which checks for the final address being
1346 if ((flags
& (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa
>= 4)) {
1347 printf(" if (instruction & 0x%1X)\n",((flags
& fieldval('e')) ? 0x7 : ((flags
& fieldval('w')) ? 0x3 : 0x1)));
1349 /* NOTE: If we change this to a SignalException(), we must
1350 ensure that the following opcode processing is not
1351 executed. i.e. the code falls straight out to the simulator
1353 printf(" sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
1358 /* The extended condition codes only appeared in ISA IV */
1359 if ((flags
& fieldval('p')) && (doisa
< 4)) {
1360 printf(" if (condition_code != 0)\n");
1362 printf(" SignalException(ReservedInstruction,instruction);\n");
1367 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && (GETDATASIZE() != WORD
)) {
1368 fprintf(stderr
,"Error in opcode table: WORD32 set for non-WORD opcode\n");
1373 /* The R4000 book differs slightly from the MIPS IV ISA
1374 manual. An example is the sign-extension of a 64-bit processor
1375 SUBU operation, and what is meant by an Undefined Result. This
1376 is now provided purely as a warning. After examining a HW
1377 implementation, this is now purely a warning... and the actual
1378 operation is performed, with possibly undefined results. */
1379 if (((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) && (features
& FEATURE_WARN_RESULT
)) {
1380 /* The compiler should optimise out an OR with zero */
1381 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
1382 printf(" UndefinedResult();\n") ;
1385 /* Check that the source is a 32bit value */
1386 if ((MIPS_DECODE
[loop
].flags
& WORD32
) && proc64
) {
1387 /* The compiler should optimise out an OR with zero */
1388 printf(" if (%s | %s)\n",((flags
& fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags
& fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
1389 printf(" UndefinedResult();\n") ;
1396 build_instruction (doisa
, features
, 0, &MIPS_DECODE
[loop
]);
1400 printf(" break ;\n") ;
1404 printf("default : /* Unrecognised instruction */\n") ;
1405 printf(" SignalException(ReservedInstruction,instruction);\n") ;
1406 printf(" break ;\n") ;
1409 /* Handle mips16 instructions. The switch table looks like this:
1410 0 - 31: I, RI, and RRI instructions by major.
1411 32 - 35: ISHIFT instructions by function + 32
1412 36 - 37: RRI_A instructions by function + 36
1413 38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
1414 46 - 49: RRR instructions by function + 46
1415 50 - 81: RR instructions by minor + 50 (except for minor == 0)
1416 82 - 89: I64 and RI64 instructions by funct + 82
1417 90 - 97: jalr (RR minor 0) by y + 90
1419 printf ("else {\n");
1420 printf ("static int extendval;\n");
1421 printf ("static int have_extendval;\n");
1422 printf ("int num = ((instruction >> %d) & 0x%08X);\n",
1423 MIPS16OP_SH_OP
, MIPS16OP_MASK_OP
);
1424 printf ("switch (num)\n{\n");
1425 printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
1426 printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
1427 printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
1428 printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
1429 printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
1430 printf (" if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
1431 printf (" break;\n");
1432 printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
1433 printf ("default: break;\n}\n");
1434 printf ("switch (num)\n{\n");
1436 for (loop
= 0; loop
< sizeof MIPS16_DECODE
/ sizeof MIPS16_DECODE
[0]; loop
++)
1441 if (! proc64
&& GETDATASIZEINSN (&MIPS16_DECODE
[loop
]) == DOUBLEWORD
)
1444 bitmap
= MIPS16_DECODE
[loop
].bitmap
;
1445 switch (MIPS16_DECODE
[loop
].mark
)
1450 num
= bitmap_val (bitmap
, 11, 5);
1453 num
= 32 + bitmap_val (bitmap
, 0, 2);
1456 num
= 36 + bitmap_val (bitmap
, 4, 1);
1461 num
= 38 + bitmap_val (bitmap
, 8, 3);
1464 num
= 46 + bitmap_val (bitmap
, 0, 2);
1470 minor
= bitmap_val (bitmap
, 0, 5);
1474 num
= 90 + bitmap_val (bitmap
, 5, 3);
1479 num
= 82 + bitmap_val (bitmap
, 8, 3);
1485 printf ("case %d: /* \"%s\" %s */\n", num
, MIPS16_DECODE
[loop
].name
,
1490 build_mips16_operands (bitmap
);
1494 /* build_instruction doesn't know about extend. */
1496 build_instruction (doisa
, features
, 1, &MIPS16_DECODE
[loop
]);
1499 printf (" extendval = ext;\n");
1500 printf (" have_extendval = 1;\n");
1505 printf (" break ;\n") ;
1508 printf ("default : /* Unrecognised instruction */\n") ;
1509 printf (" SignalException(ReservedInstruction,instruction);\n") ;
1510 printf (" break ;\n") ;
1513 printf("#endif /* simulator engine */\n");
1518 /* Output the code to execute an instruction, assuming the operands
1519 have already been extracted. */
1522 build_instruction (doisa
, features
, mips16
, insn
)
1524 unsigned int features
;
1526 const struct instruction
*insn
;
1528 int gprlen
=((features
& FEATURE_GP64
) ? 64 : 32);
1529 int proc64
= ((features
& FEATURE_PROC32
) ? 0 : -1);
1530 char *regtype
= ((gprlen
== 64) ? "uword64" : "unsigned int");
1532 switch (insn
->type
) {
1533 /* TODO: To make these easier to edit and maintain, they should
1534 actually be provided as source macros (or inline functions)
1535 OUTSIDE this main switch statement. The PPC simulator has a
1536 neater scheme for describing the instruction sequences. */
1541 char *signed_basetype
= "unknown";
1542 char *unsigned_basetype
= "unknown";
1544 switch (GETDATASIZEINSN(insn
)) {
1546 signed_basetype
= "signed int";
1547 unsigned_basetype
= "unsigned int";
1550 signed_basetype
= "word64";
1551 unsigned_basetype
= "uword64";
1554 fprintf(stderr
,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn
));
1558 if ((insn
->type
) == ADD
) {
1559 printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype
, unsigned_basetype
);
1560 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
1561 if (insn
->flags
& OVERFLOW
) {
1562 printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
1563 printf(" SignalException(IntegerOverflow);\n");
1566 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
1567 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1568 else /* only sign-extend when placing 32bit result in 64bit processor */
1569 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1571 printf(" %s temp = (%s)(op1 - op2);\n", unsigned_basetype
, unsigned_basetype
);
1572 printf(" %s tempS = (%s)temp;\n", signed_basetype
, signed_basetype
);
1573 if (insn
->flags
& OVERFLOW
) { /* different signs => overflow if result_sign != arg_sign */
1574 printf(" if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
1575 printf(" SignalException(IntegerOverflow);\n");
1578 /* UNSIGNED 32bit operations on a 64bit processor should
1579 *STILL* be sign-extended. We have cheated in the
1580 data-structure, by not marking it with UNSIGNED, and not
1581 setting OVERFLOW. */
1582 if (!proc64
|| (insn
->flags
& UNSIGNED
) || (GETDATASIZEINSN(insn
) == DOUBLEWORD
))
1583 printf(" GPR[destreg] = (%s)temp;\n",regtype
);
1584 else /* only sign-extend when placing 32bit result in 64bit processor */
1585 printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype
);
1591 if (features
& FEATURE_WARN_LOHI
) {
1592 printf(" CHECKHILO(\"Multiplication\");\n");
1595 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
1596 printf(" uword64 mid;\n");
1597 printf(" uword64 midhi;\n");
1598 printf(" uword64 temp;\n");
1599 if ((insn
->flags
& UNSIGNED
) == 0)
1601 printf(" int sign = 0;\n");
1602 printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
1603 printf(" if (op2 < 0) { op2 = - op2; ++sign; }\n");
1605 printf(" LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
1606 printf(" HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
1607 printf(" mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
1608 printf(" midhi = SET64HI(WORD64LO(mid));\n");
1609 printf(" temp = (LO + midhi);\n");
1610 printf(" if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n");
1611 printf(" HI += 1;\n");
1612 printf(" HI += WORD64HI(mid);\n");
1613 printf(" mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
1614 printf(" midhi = SET64HI(WORD64LO(mid));\n");
1615 printf(" LO = (temp + midhi);\n");
1616 printf(" if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n");
1617 printf(" HI += 1;\n");
1618 printf(" HI += WORD64HI(mid);\n");
1619 if ((insn
->flags
& UNSIGNED
) == 0)
1620 printf(" if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n");
1622 if (insn
->flags
& UNSIGNED
)
1623 printf(" uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
1625 printf(" uword64 temp = ((word64) op1 * (word64) op2);\n");
1626 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1627 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1634 int boolU
= (insn
->flags
& UNSIGNED
);
1636 if (features
& FEATURE_WARN_LOHI
) {
1637 printf(" CHECKHILO(\"Division\");\n");
1640 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
1641 printf(" LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1642 printf(" HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU
? "u" : ""),'%',(boolU
? "u" : ""));
1644 printf(" LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU
? "unsigned " : ""),(boolU
? "unsigned " : ""));
1645 printf(" HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU
? "unsigned " : ""),'%',(boolU
? "unsigned " : ""));
1653 int datalen
= GETDATASIZEINSN(insn
);
1654 int bits
= ((datalen
== WORD
) ? 32 : 64);
1655 char *ltype
= ((datalen
== WORD
) ? "unsigned int" : "uword64");
1657 /* Check that the specified SHIFT is valid: */
1658 if ((datalen
== BYTE
) || (datalen
== HALFWORD
)) {
1659 fprintf(stderr
,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn
->name
);
1662 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
1663 fprintf(stderr
,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn
->name
);
1666 if (!(insn
->flags
& LEFT
) && !(insn
->flags
& RIGHT
)) {
1667 fprintf(stderr
,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn
->name
);
1670 if ((insn
->flags
& LOGICAL
) && (insn
->flags
& ARITHMETIC
)) {
1671 fprintf(stderr
,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn
->name
);
1674 if (!(insn
->flags
& LOGICAL
) && !(insn
->flags
& ARITHMETIC
)) {
1675 fprintf(stderr
,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn
->name
);
1678 if ((insn
->flags
& LEFT
) && (insn
->flags
& ARITHMETIC
)) {
1679 fprintf(stderr
,"Arithmetic LEFT shift \"%s\" specified\n",insn
->name
);
1683 /* Work around an MSC code generation bug by precomputing a value
1684 * with the sign bit set. */
1685 if (insn
->flags
& ARITHMETIC
)
1686 printf(" %s highbit = (%s)1 << %d;\n", ltype
, ltype
, bits
- 1);
1688 /* If register specified shift, then extract the relevant shift amount: */
1689 if (insn
->flags
& REG
)
1690 printf(" op1 &= 0x%02X;\n",(bits
- 1));
1692 /* If HI32 specified, then shift range is 32..63 */
1693 if (insn
->flags
& HI32
)
1694 printf(" op1 |= (1 << 5);\n");
1696 /* We do not need to perform pre-masking with 0xFFFFFFFF when
1697 dealing with 32bit shift lefts, since the sign-extension
1698 code will replace any remaining hi-bits: */
1699 if (insn
->flags
& LEFT
)
1700 printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
1702 printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits
== 32) ? " & 0xFFFFFFFF" : ""));
1704 /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
1705 don't do this if op1 is zero, since it is not needed and
1706 since that would cause an undefined shift of the number of
1707 bits in the type. */
1708 if (insn
->flags
& ARITHMETIC
)
1709 printf(" GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype
,bits
);
1711 /* Ensure WORD values are sign-extended into 64bit registers */
1712 if ((bits
== 32) && (gprlen
== 64))
1713 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits
);
1718 if (insn
->flags
& (HI
| LO
)) {
1719 char *regname
= ((insn
->flags
& LO
) ? "LO" : "HI");
1720 if (insn
->flags
& LEFT
)
1721 printf(" GPR[destreg] = %s;\n",regname
);
1723 if (features
& FEATURE_WARN_LOHI
) {
1724 printf(" if (%sACCESS != 0)\n",regname
);
1725 printf(" sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname
);
1727 printf(" %s = op1;\n",regname
);
1729 if (features
& FEATURE_WARN_LOHI
)
1730 printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname
);
1732 if (insn
->flags
& SHIFT16
)
1733 printf(" GPR[destreg] = (op2 << 16);\n");
1735 /* perform conditional move */
1736 if (!(insn
->flags
& EQ
)) {
1737 fprintf(stderr
,"Standard conditional %s does not have the equality flag\n",insn
->name
);
1740 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
1741 printf(" GPR[destreg] = op1;\n");
1746 printf(" SyncOperation(op1);\n");
1750 printf(" SignalException(SystemCall,instruction);\n");
1754 printf(" SignalException(BreakPoint,instruction);\n");
1759 int boolNOT
= (insn
->flags
& NOT
);
1760 int boolEQ
= (insn
->flags
& EQ
);
1761 int boolGT
= (insn
->flags
& GT
);
1762 int boolLT
= (insn
->flags
& LT
);
1763 int boolU
= (insn
->flags
& UNSIGNED
);
1765 if (boolGT
&& boolLT
) {
1766 fprintf(stderr
,"GT and LT specified for \"%s\"\n",insn
->name
);
1770 if (boolNOT
&& (boolGT
|| boolLT
)) {
1771 fprintf(stderr
,"NOT specified with GT or LT specified for \"%s\"\n",insn
->name
);
1775 printf(" if ((%sword64)op1 ",(boolU
? "u" : ""));
1776 printf("%c%s",(boolNOT
? '!' : (boolLT
? '<' : (boolGT
? '>' : '='))),(boolEQ
? "=" : ""));
1777 printf(" (%sword64)op2)\n",(boolU
? "u" : ""));
1778 printf(" SignalException(Trap,instruction);\n");
1784 int boolU
= (insn
->flags
& UNSIGNED
);
1786 if (!(insn
->flags
& LT
)) {
1787 fprintf(stderr
,"Set instruction without LT specified \"%s\"\n",insn
->name
);
1791 printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU
? "u" : ""),(boolU
? "u" : ""));
1792 printf(" GPR[destreg] = 1;\n");
1794 printf(" GPR[destreg] = 0;\n");
1799 printf(" GPR[destreg] = (op1 & op2);\n");
1803 /* The default mips16 nop instruction does an or to register
1804 zero; catch that case, so that we don't get useless warnings
1805 from the simulator. */
1807 printf (" if (destreg != 0)\n");
1808 printf(" GPR[destreg] = %s(op1 | op2);\n",((insn
->flags
& NOT
) ? "~" : ""));
1812 printf(" GPR[destreg] = (op1 ^ op2);\n");
1816 printf(" decode_coproc(instruction);\n");
1820 /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
1821 /* The virtual address is translated to a physical address using the TLB */
1822 /* The hint specifies a cache operation for that address */
1823 printf(" uword64 vaddr = (op1 + offset);\n");
1824 printf(" uword64 paddr;\n");
1825 printf(" int uncached;\n");
1826 /* NOTE: We are assuming that the AddressTranslation is a load: */
1827 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
1828 printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
1831 case MADD16
: /* VR4100 specific multiply-add instructions */
1832 /* Some of this code is shared with the standard multiply
1833 routines, so an effort should be made to merge where
1835 if (features
& FEATURE_WARN_LOHI
) {
1836 printf(" CHECKHILO(\"Multiply-Add\");\n");
1838 if (features
& FEATURE_WARN_RESULT
) {
1839 /* Give user a warning if either op1 or op2 are not 16bit signed integers */
1840 printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
1841 printf(" sim_warning(\"MADD16 operation with non-16bit operands\");\n");
1844 printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
1845 if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
1846 printf(" LO = LO + temp;\n");
1848 printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
1849 printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype
);
1850 printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype
);
1855 case RSVD
: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
1857 printf(" if (CoProcPresent(3))\n");
1858 printf(" SignalException(CoProcessorUnusable);\n");
1861 printf(" SignalException(ReservedInstruction,instruction);\n");
1865 if (insn
->flags
& LINK
) {
1866 if (!(insn
->flags
& REG
))
1867 printf(" int destreg = 31;\n");
1868 printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
1869 mips16
? 2 : 4, mips16
? 2 : 4);
1872 if (insn
->flags
& NOT
)
1873 printf(" op1 ^= 1;\n");
1875 printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
1876 printf(" so we just truncate it to 32 bits here. */\n");
1877 printf(" op1 = WORD64LO(op1);\n");
1878 printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
1879 printf(" DSPC = op1;\n");
1880 if (insn
->flags
& LINK
)
1881 printf(" JALDELAYSLOT();\n");
1883 printf(" DELAYSLOT();\n");
1886 case BRANCH
: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
1887 if (insn
->flags
& FP
) {
1889 printf(" if (condition_code != 0)\n");
1890 printf(" SignalException(ReservedInstruction,instruction);\n");
1891 printf(" else {\n");
1893 /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
1894 printf(" int condition = (%s == boolean);\n",((doisa
< 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
1896 if ((insn
->flags
& NOT
) && !(insn
->flags
& EQ
)) {
1897 fprintf(stderr
,"NOT specified when not EQ in \"%s\"\n",insn
->name
);
1900 if ((insn
->flags
& NOT
) && (insn
->flags
& (GT
| LT
))) {
1901 fprintf(stderr
,"NOT specified with GT or LT in \"%s\"\n",insn
->name
);
1905 if (insn
->flags
& GT
)
1906 printf(" int condition = (op1 >%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
1908 if (insn
->flags
& LT
)
1909 printf(" int condition = (op1 <%s 0);\n",((insn
->flags
& EQ
) ? "=" : ""));
1911 if (insn
->flags
& EQ
)
1912 printf(" int condition = (op1 %c= op2);\n",((insn
->flags
& NOT
) ? '!' : '='));
1915 if (insn
->flags
& LINK
) {
1916 if (features
& FEATURE_WARN_R31
) {
1917 printf(" if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS
,OP_MASK_RS
);
1918 printf(" sim_warning(\"Branch with link using r31 as source operand\");\n");
1920 printf(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
1924 printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
1925 printf(" if (condition) {\n");
1926 printf(" DSPC = (PC + offset);\n");
1927 printf(" DELAYSLOT();\n");
1930 /* No delayed slots for mips16 branches. */
1931 printf(" if (condition)\n");
1932 printf(" PC = PC + offset;\n");
1934 if ((insn
->flags
& FP
) && (doisa
!= 1)) {
1935 printf(" else if (likely) {\n");
1936 printf(" NULLIFY();\n");
1938 } else if (insn
->flags
& LIKELY
) {
1940 printf(" NULLIFY();\n");
1942 if ((insn
->flags
& FP
) && (doisa
< 4))
1946 case PREFETCH
: /* The beginning is shared with normal load operations */
1950 int isload
= ((insn
->type
== LOAD
) || (insn
->type
== PREFETCH
));
1952 char *accesslength
= "<UNKNOWN>";
1954 switch (GETDATASIZEINSN(insn
)) {
1957 accesslength
= "AccessLength_BYTE";
1962 accesslength
= "AccessLength_HALFWORD";
1967 accesslength
= "AccessLength_WORD";
1972 accesslength
= "AccessLength_DOUBLEWORD";
1976 if (insn
->flags
& REG
)
1977 printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
1979 printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
1980 printf(" uword64 paddr;\n");
1981 printf(" int uncached;\n");
1983 /* The following check should only occur on normal (non-shifted) memory loads */
1984 if ((datalen
!= 1) && !(insn
->flags
& (LEFT
| RIGHT
))) {
1985 printf(" if ((vaddr & %d) != 0)\n",(datalen
- 1));
1986 printf(" SignalException(%s);\n",(isload
? "AddressLoad" : "AddressStore"));
1991 printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload
? "isLOAD" : "isSTORE"));
1993 if (insn
->type
== PREFETCH
)
1994 printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
1997 printf(" uword64 memval;\n");
1999 if ((insn
->flags
& COPROC
) && ((datalen
!= 4) && (datalen
!= 8))) {
2000 fprintf(stderr
,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2004 if (insn
->flags
& (LEFT
| RIGHT
)) {
2005 if ((insn
->flags
& LEFT
) && (insn
->flags
& RIGHT
)) {
2006 fprintf(stderr
,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn
->name
);
2013 fprintf(stderr
,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn
->name
);
2016 /* fall through to... */
2019 printf(" uword64 mask = %d;\n",((datalen
== 8) ? 0x7 : 0x3));
2020 printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
2021 printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
2022 printf(" int byte;\n");
2023 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
2024 printf(" byte = ((vaddr & mask) ^ bigend);\n");
2025 printf(" if (%s!ByteSwapMem)\n",((insn
->flags
& LEFT
) ? "!" : ""));
2026 printf(" paddr &= ~mask;\n");
2029 if (insn
->flags
& LEFT
)
2030 printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
2032 printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen
- 1));
2035 if (insn
->flags
& LEFT
) {
2037 /* For WORD transfers work out if the value will
2038 be in the top or bottom of the DOUBLEWORD
2041 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2043 if (proc64
&& (datalen
== 4)) {
2044 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2045 printf(" memval >>= 32;\n");
2049 printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen
- 1),(datalen
- 1));
2050 if (proc64
&& (datalen
== 4))
2051 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2052 } else { /* store */
2053 printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen
- 1));
2055 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2057 /* TODO: This is duplicated in the LOAD code
2058 above - and the RIGHT LOAD and STORE code
2059 below. It should be merged if possible. */
2060 if (proc64
&& (datalen
== 4)) {
2061 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2062 printf(" memval <<= 32;\n");
2066 printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
2068 } else { /* RIGHT */
2071 build_endian_shift(proc64
,datalen
,2,s_right
,32);
2073 if (proc64
&& (datalen
== 4)) {
2074 printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
2075 printf(" memval >>= 32;\n");
2080 printf(" uword64 srcmask;\n");
2081 /* All of this extra code is just a bodge
2082 required because some hosts don't allow
2083 ((v) << 64). The SPARC just leaves the (v)
2084 value un-touched. */
2085 printf(" if (byte == 0)\n");
2086 printf(" srcmask = 0;\n");
2088 printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen
);
2089 printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
2091 if (proc64
&& (datalen
== 4))
2092 printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
2093 } else { /* store */
2094 printf(" memval = ((uword64) op2 << (byte * 8));\n");
2095 build_endian_shift(proc64
,datalen
,2,s_left
,32);
2096 printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength
);
2103 fprintf(stderr
,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn
->name
);
2106 } else { /* normal memory transfer */
2107 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2108 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2110 /* TODO: The R4000 documentation states that a LWU
2111 instruction executed when in a 32bit processor mode
2112 should cause a ReservedInstruction exception. This
2113 will mean adding a run-time check into the code
2118 #if 1 /* see the comments attached to LOADDRMASK above */
2119 printf(" uword64 mask = 0x7;\n");
2121 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2123 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2124 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2125 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2126 printf(" unsigned int byte;\n");
2128 /* TODO: This should really also check for 32bit world performing 32bit access */
2129 if (datalen
!= 8) /* not for DOUBLEWORD */
2130 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2132 printf(" memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength
);
2134 /* The following will only make sense if the
2135 "LoadMemory" above returns a DOUBLEWORD entity */
2136 if (datalen
!= 8) { /* not for DOUBLEWORD */
2148 valmask
= 0xFFFFFFFF;
2152 fprintf(stderr
,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen
,insn
->name
);
2155 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2156 /* NOTE: The R4000 user manual has the COP_LW
2157 occuring in the same cycle as the rest of the
2158 instruction, yet the MIPS IV shows the operation
2159 happening on the next cycle. To keep the simulator
2160 simple, this code follows the R4000
2161 manual. Experimentation with a silicon
2162 implementation will be needed to ascertain the
2163 correct operation. */
2164 if (insn
->flags
& COPROC
)
2165 printf(" COP_LW(%s,destreg,(unsigned int)",
2166 ((insn
->flags
& REG
)
2168 : "((instruction >> 26) & 0x3)"));
2170 printf(" GPR[destreg] = (");
2172 if (insn
->flags
& SIGNEXTEND
)
2173 printf("SIGNEXTEND(");
2174 printf("((memval >> (8 * byte)) & 0x%08X)",valmask
);
2175 if (insn
->flags
& SIGNEXTEND
)
2176 printf(",%d)",(datalen
* 8));
2179 if (insn
->flags
& COPROC
)
2180 printf(" COP_LD(%s,destreg,memval);;\n",
2181 ((insn
->flags
& REG
)
2183 : "((instruction >> 26) & 0x3)"));
2185 printf(" GPR[destreg] = memval;\n");
2187 } else { /* store operation */
2188 if ((datalen
== 1) || (datalen
== 2)) {
2190 #if 1 /* see the comments attached to LOADDRMASK above */
2191 printf(" uword64 mask = 0x7;\n");
2193 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2195 printf(" unsigned int shift = %d;\n",(datalen
>> 1));
2196 printf(" unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
2197 printf(" unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
2198 printf(" unsigned int byte;\n");
2200 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
2201 printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
2202 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2204 if (datalen
== 4) { /* SC and SW */
2205 #if 1 /* see the comments attached to LOADDRMASK above */
2206 printf(" uword64 mask = 0x7;\n");
2208 printf(" uword64 mask = %d;\n",(proc64
? 0x7 : 0x3));
2210 printf(" unsigned int byte;\n");
2211 printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
2212 printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
2213 if (insn
->flags
& COPROC
)
2214 printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
2215 ((insn
->flags
& REG
)
2217 : "((instruction >> 26) & 0x3)"),
2218 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2220 printf(" memval = ((uword64) op2 << (8 * byte));\n");
2221 } else { /* SD and SCD */
2222 if (!(insn
->flags
& COPROC
) && ((datalen
== 8) || ((datalen
== 4) & (insn
->flags
& UNSIGNED
))) && !proc64
) {
2223 fprintf(stderr
,"Operation not available with 32bit wide memory access \"%s\"\n",insn
->name
);
2226 if (insn
->flags
& COPROC
)
2227 printf(" memval = (uword64)COP_SD(%s,%s);\n",
2228 ((insn
->flags
& REG
)
2230 : "((instruction >> 26) & 0x3)"),
2231 ((insn
->flags
& FP
) ? "fs" : "destreg"));
2233 printf(" memval = op2;\n");
2236 if (insn
->flags
& ATOMIC
)
2237 printf(" if (LLBIT)\n");
2240 printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength
);
2244 if (insn
->flags
& ATOMIC
) {
2245 if ((datalen
!= 4) && (datalen
!= 8)) {
2246 fprintf(stderr
,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn
->name
);
2250 printf(" LLBIT = 1;\n");
2252 /* The documentation states that:
2254 SC *WILL* fail if coherent store into the same
2255 block occurs, or if an exception occurs between
2256 the LL and SC instructions.
2258 SC *MAY* fail if a load, store or prefetch is
2259 executed on the processor (VR4300 doesn't seem
2260 to), or if the instructions between the LL and
2261 SC are not in a 2048byte contiguous VM range.
2263 SC *MUST* have been preceded by an LL
2264 (i.e. LLBIT will be set), and it must use the
2265 same Vaddr, Paddr and cache-coherence algorithm
2266 as the LL (which means we should store this
2267 information from the load-conditional).
2269 printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT
,OP_MASK_RT
);
2280 /* This code could be merged with the PREFIX generation above: */
2281 printf(" uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
2282 printf(" uword64 paddr;\n");
2283 printf(" int uncached;\n");
2284 printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
2285 printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
2289 if (insn
->flags
& CONTROL
) {
2290 /* The following "magic" of interpreting the FP
2291 control-register number would not be needed if we were not
2292 trying to match our internal register numbers with those
2294 printf(" if (to) {\n");
2296 printf(" if (fs == 0) {\n");
2297 printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
2298 printf(" } else if (fs == 31) {\n");
2299 printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
2300 printf(" } /* else NOP */\n");
2301 printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
2303 printf(" if (fs == 0) {\n");
2304 printf(" FCR0 = WORD64LO(GPR[ft]);\n");
2305 printf(" } else if (fs == 31) {\n");
2306 printf(" FCR31 = WORD64LO(GPR[ft]);\n");
2307 printf(" } /* else NOP */\n");
2308 printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
2310 printf(" } else { /* control from */\n");
2312 printf(" if (fs == 0) {\n");
2313 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
2314 printf(" } else if (fs == 31) {\n");
2315 printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
2316 printf(" } /* else NOP */\n");
2318 printf(" if (fs == 0) {\n");
2319 printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
2320 printf(" } else if (fs == 31) {\n");
2321 printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
2322 printf(" } /* else NOP */\n");
2326 printf(" if (to) {\n");
2327 if (GETDATASIZEINSN(insn
) == WORD
) {
2329 printf(" if (SizeFGR() == 64) {\n");
2330 printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
2331 printf(" } else { \n");
2332 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2335 printf(" if (SizeFGR() == 64)\n");
2336 printf(" FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
2338 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
2339 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2341 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2343 printf(" if (SizeFGR() == 64) {\n");
2344 printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
2345 printf(" } else\n");
2346 printf(" if ((fs & 0x1) == 0)\n");
2348 printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
2349 printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
2351 if (features
& FEATURE_WARN_RESULT
) {
2353 printf(" UndefinedResult();\n");
2356 printf(" if (SizeFGR() == 64) {\n");
2357 printf(" FGR[fs] = GPR[ft];\n");
2358 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2359 printf(" } else\n");
2360 printf(" if ((fs & 0x1) == 0)\n");
2362 printf(" FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
2363 printf(" FGR[fs] = WORD64LO(GPR[ft]);\n");
2364 printf(" fpr_state[fs + 1] = fmt_uninterpreted;\n");
2365 printf(" fpr_state[fs] = fmt_uninterpreted;\n");
2367 if (features
& FEATURE_WARN_RESULT
) {
2369 printf(" UndefinedResult();\n");
2373 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
2376 printf(" } else {\n");
2377 if (GETDATASIZEINSN(insn
) == WORD
) {
2378 if (doisa
< 4) /* write-back occurs in next cycle */
2379 printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
2380 else /* in this cycle */
2381 printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
2382 } else if (GETDATASIZEINSN(insn
) == DOUBLEWORD
) {
2384 printf(" if (SizeFGR() == 64) {\n");
2385 printf(" PENDING_FILL(ft,FGR[fs]);\n");
2386 printf(" } else\n");
2387 printf(" if ((fs & 0x1) == 0) {\n");
2388 printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
2389 printf(" } else {\n");
2390 printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
2391 if (features
& FEATURE_WARN_RESULT
)
2392 printf(" UndefinedResult();\n");
2395 printf(" if (SizeFGR() == 64)\n");
2396 printf(" GPR[ft] = FGR[fs];\n");
2398 printf(" if ((fs & 0x1) == 0)\n");
2399 printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
2400 printf(" else {\n");
2401 printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
2402 if (features
& FEATURE_WARN_RESULT
)
2403 printf(" UndefinedResult();\n");
2407 fprintf(stderr
,"Invalid data width specified in FPU Move operation\n");
2415 if (insn
->flags
& CONDITIONAL
) {
2416 if (insn
->flags
& INTEGER
) { /* moving GPR - testing FGR */
2417 printf(" if (GETFCC(condition_code) == boolean)\n");
2418 printf(" GPR[destreg] = op1;\n");
2420 if (insn
->flags
& EQ
) /* moving FGR - testing GPR */
2421 printf(" if (op2 %c= 0)\n",((insn
->flags
& NOT
) ? '!' : '='));
2423 printf(" if (GETFCC(condition_code) == boolean)\n");
2424 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
2426 printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
2428 } else { /* simple MOVE */
2429 printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
2434 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2435 printf(" SignalException(ReservedInstruction,instruction);\n");
2437 printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
2441 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2442 printf(" SignalException(ReservedInstruction,instruction);\n");
2444 printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
2448 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2449 printf(" SignalException(ReservedInstruction,instruction);\n");
2451 printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2455 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2456 printf(" SignalException(ReservedInstruction,instruction);\n");
2458 printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2462 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2463 printf(" SignalException(ReservedInstruction,instruction);\n");
2465 printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
2469 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2470 printf(" SignalException(ReservedInstruction,instruction);\n");
2472 printf(" StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn
->flags
& RECIP
) ? "Recip" : ""));
2483 switch (insn
->type
) {
2485 op
= "FP_RM_TOPINF";
2488 op
= "FP_RM_TOMINF";
2491 op
= "FP_RM_TOZERO";
2494 op
= "FP_RM_NEAREST";
2497 fprintf(stderr
,"Error: Handled missing for FP reason code %d\n",insn
->type
);
2501 switch (GETDATASIZEINSN(insn
)) {
2509 fprintf(stderr
,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op
);
2512 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2513 printf(" SignalException(ReservedInstruction,instruction);\n");
2515 printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type
,op
,type
);
2522 switch (GETDATASIZEINSN(insn
)) {
2524 type
= "fmt_single";
2527 type
= "fmt_double";
2536 fprintf(stderr
,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn
));
2540 /* Not all combinations of conversion are valid at the
2541 moment: When converting to a fixed-point format, only
2542 floating-point sources are allowed. */
2543 printf(" if ((format == %s) | %s)\n",type
,((insn
->flags
& FIXED
) ? "((format == fmt_long) || (format == fmt_word))": "0"));
2544 printf(" SignalException(ReservedInstruction,instruction);\n");
2546 printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type
,type
);
2551 if (insn
->flags
& MULTIPLY
) {
2553 switch (GETDATASIZEINSN(insn
)) {
2555 type
= "fmt_single";
2558 type
= "fmt_double";
2561 fprintf(stderr
,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn
));
2564 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
);
2566 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2567 printf(" SignalException(ReservedInstruction,instruction);\n");
2569 printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2574 if (insn
->flags
& MULTIPLY
) {
2576 switch (GETDATASIZEINSN(insn
)) {
2578 type
= "fmt_single";
2581 type
= "fmt_double";
2584 fprintf(stderr
,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn
));
2587 if (insn
->flags
& NOT
)
2588 printf (" StoreFPR(destreg,%s,Negate(Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
2589 type
, type
, type
, type
, type
, type
, type
);
2591 printf (" StoreFPR(destreg,%s,Add(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
2592 type
, type
, type
, type
, type
, type
);
2594 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2595 printf(" SignalException(ReservedInstruction,instruction);\n");
2597 printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
2602 /* For the MIPS I,II or III there *MUST* be at least one
2603 instruction between the compare that sets a condition code
2604 and the branch that tests it. NOTE: However the hardware
2605 does not detect this condition. */
2606 /* Explicitly limit the operation to S and D formats: */
2607 printf(" if ((format != fmt_single) && (format != fmt_double))\n");
2608 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2609 printf(" else {\n");
2611 printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
2612 printf(" SignalException(ReservedInstruction,instruction);\n") ;
2616 printf(" int ignore = 0;\n");
2617 printf(" int less = 0;\n");
2618 printf(" int equal = 0;\n");
2619 printf(" int unordered = 1;\n");
2620 printf(" uword64 ofs = ValueFPR(fs,format);\n");
2621 printf(" uword64 oft = ValueFPR(ft,format);\n");
2622 printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
2623 printf(" if (FCSR & FP_ENABLE(IO)) {\n");
2624 printf(" FCSR |= FP_CAUSE(IO);\n");
2625 printf(" SignalException(FPE);\n");
2626 printf(" ignore = 1;\n");
2628 printf(" } else {\n");
2629 printf(" less = Less(ofs,oft,format);\n");
2630 printf(" equal = Equal(ofs,oft,format);\n");
2631 printf(" unordered = 0;\n");
2633 printf(" if (!ignore) {\n");
2634 printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
2635 printf(" SETFCC(condition_code,condition);\n");
2642 fprintf(stderr
,"Unrecognised opcode type %d\n",insn
->type
) ;
2647 /*---------------------------------------------------------------------------*/
2649 /* The command-line feature controls are presented in a similar style
2650 to those offered by GCC, in the aim of providing a consistent
2651 interface to the user. */
2653 T_NONE
, /* no argument - mask and value fields control "feature" definition */
2654 T_NUM
, /* numeric argument - optionally preceded by '=' - mask field defines maximum value */
2655 T_STRING
/* string argument - optionally prcededed by '=' */
2664 } machine_options
[] = {
2665 {"ips", T_NUM
, MASK_ISA
,0,"\tSelect MIPS ISA version"},
2666 {"cpu", T_STRING
,0,0,"\t\tSelect particular MIPS architecture"},
2667 {"gp64", T_NONE
, FEATURE_GP64
,FEATURE_GP64
,"\t\t\tSelect 64bit GP registers"},
2668 {"gp32", T_NONE
, FEATURE_GP64
,0,"\t\t\tSelect 32bit GP registers"},
2669 {"no-fp", T_NONE
, FEATURE_HASFPU
,0,"\t\tDisable FP simulation"},
2670 {"single-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),(FEATURE_FPSINGLE
| FEATURE_HASFPU
),"\t\tSelect single precision only FPU"},
2671 {"double-float",T_NONE
, (FEATURE_FPSINGLE
| FEATURE_HASFPU
),FEATURE_HASFPU
,"\t\tSelect double precision FPU"},
2675 /* The following architecture identies are those accepted by the "-mcpu" option: */
2676 struct architectures
{
2677 const char *name
; /* ASCII string identifier for command-line, no white-space allowed */
2678 unsigned int idflag
; /* or-ed into "isa" value */
2681 static const struct architectures available_architectures
[] = {
2682 {"4100",ARCH_VR4100
}, /* NEC MIPS VR4100 */
2683 {0, 0} /* terminator */
2686 /*---------------------------------------------------------------------------*/
2694 fprintf(stderr
,"%s: Construct a MIPS simulator engine.\n",name
);
2697 The output of this program is a block of 'C' code designed to be\n\
2698 included into the main simulation control loop of a device specific\n\
2701 fprintf(stderr
,"\nOptions:\n");
2702 fprintf(stderr
," -h --help\t\tProvide this help text\n");
2703 fprintf(stderr
," -f --fast\t\tProvide the fastest possible engine (i.e. no statistics)\n");
2704 fprintf(stderr
," -w --warnings\t\tEnable all the simulator engine warnings\n");
2706 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++) {
2707 fprintf(stderr
," -m%s",machine_options
[loop
].name
);
2708 switch (machine_options
[loop
].type
) {
2710 fprintf(stderr
,"N (range 0..%d)",machine_options
[loop
].mask
);
2715 fprintf(stderr
,"=name");
2719 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",name
,machine_options
[loop
].type
);
2722 fprintf(stderr
,"%s\n",machine_options
[loop
].desc
);
2725 fprintf(stderr
,"\nAvailable \"-mcpu\" architectures: ");
2726 for (loop
= 0; (available_architectures
[loop
].name
!= 0); loop
++)
2727 fprintf(stderr
,"%s ",available_architectures
[loop
].name
);
2728 fprintf(stderr
,"\n\n");
2731 The \"trace\" and \"warnings\" options do not define the output stream.\n\
2732 They only inform the code that includes the constructed engine to provide\n\
2733 the required features.\n\n\
2734 The \"-mips0\" option forces the construction of a simulator supporting\n\
2735 the highest available MIPS ISA supported.\n");
2740 /*---------------------------------------------------------------------------*/
2748 char *progname
= argv
[0];
2749 unsigned int doarch
= DEF_ISA
;
2750 unsigned int features
= 0; /* default state */
2753 features
|= FEATURE_HASFPU
;
2755 features
|= FEATURE_PROC32
;
2757 features
|= FEATURE_FPSINGLE
;
2759 if (features
& FEATURE_PROC32
)
2760 features
&= ~FEATURE_GP64
;
2762 features
|= FEATURE_GP64
;
2765 int option_index
= 0;
2766 static struct option cmdline
[] = {
2769 {"warnings",0,0,'w'},
2773 c
= getopt_long(argc
,argv
,"hm:tw",cmdline
,&option_index
);
2775 break ; /* out of the while loop */
2778 case 'h' : /* help */
2782 case 'f' : /* fast */
2783 features
|= FEATURE_FAST
;
2786 case 'w' : /* warnings */
2787 features
|= FEATURE_WARNINGS
;
2788 /* TODO: Future extension: Allow better control over the warnings generated:
2789 disable warnings -wnone ~FEATURE_WARNINGS
2790 all possible warnings -wall FEATURE_WARNINGS
2791 pipeline stall occuring -wstall FEATURE_WARN_STALL
2792 LO/HI corruption -wlo or -whi or -wlohi or -whilo FEATURE_WARN_HILO
2793 write to zero -wzero FEATURE_WARN_ZERO actually performed in external code - though we should set a manifest
2794 bad r31 use -wr31 FEATURE_WARN_R31
2795 undefined results -wresult FEATURE_WARN_RESULT
2799 case 'm' : /* machine options */
2803 for (loop
= 0; (machine_options
[loop
].name
!= 0); loop
++)
2804 if (strncmp(machine_options
[loop
].name
,optarg
,strlen(machine_options
[loop
].name
)) == 0) {
2805 char *loptarg
= (optarg
+ strlen(machine_options
[loop
].name
));
2806 switch (machine_options
[loop
].type
) {
2809 fprintf(stderr
,"%s: Spurious characters \"%s\" at end of -m%s option\n",progname
,loptarg
,machine_options
[loop
].name
);
2812 features
&= ~(machine_options
[loop
].mask
);
2813 features
|= machine_options
[loop
].value
;
2817 if (*loptarg
&& *loptarg
== '=')
2820 if (strcmp(machine_options
[loop
].name
,"ips") == 0) {
2824 fprintf(stderr
,"%s: ISA number expected after -mips\n",progname
);
2828 num
= my_strtoul(loptarg
,&loptarg
,10);
2830 if ((num
== ULONG_MAX
) && (errno
= ERANGE
)) {
2831 fprintf(stderr
,"%s: Invalid number given to -mips option\n",progname
);
2836 fprintf(stderr
,"%s: Spurious trailing characters after ISA number \"%s\"\n",progname
,loptarg
);
2840 if (num
> MASK_ISA
) {
2841 fprintf(stderr
,"%s: ISA number %d outside acceptable range (0..%d)\n",progname
,num
,MASK_ISA
);
2845 doarch
= ((doarch
& ~MASK_ISA
) | num
);
2846 if ((num
== 0) || (num
> 2)) {
2847 if ((features
& FEATURE_PROC32
) || !(features
& FEATURE_GP64
))
2848 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp64\n",progname
,num
);
2849 features
|= FEATURE_GP64
;
2850 features
&= ~FEATURE_PROC32
;
2852 if (!(features
& FEATURE_PROC32
) || (features
& FEATURE_GP64
))
2853 fprintf(stderr
,"%s: Warning: -mips%d forcing -mgp32\n",progname
,num
);
2854 features
&= ~FEATURE_GP64
;
2855 features
|= FEATURE_PROC32
;
2858 fprintf(stderr
,"%s: FATAL: Unrecognised (numeric) machine option -m%s\n",progname
,optarg
);
2864 if (*loptarg
&& *loptarg
== '=')
2867 if (strcmp(machine_options
[loop
].name
,"cpu") == 0) {
2871 fprintf(stderr
,"%s: Architecture identifier expected after -mcpu\n",progname
);
2875 for (archloop
= 0; (available_architectures
[archloop
].name
!= 0); archloop
++) {
2876 if ((*loptarg
== 'v') || (*loptarg
== 'V'))
2879 if ((*loptarg
== 'r') || (*loptarg
== 'R'))
2882 if (strcmp(available_architectures
[archloop
].name
,loptarg
) == 0) {
2883 doarch
|= available_architectures
[archloop
].idflag
;
2888 if (available_architectures
[archloop
].name
== 0) {
2889 fprintf(stderr
,"%s: Unrecognised MIPS architecture \"%s\"\n",progname
,loptarg
);
2893 fprintf(stderr
,"%s: FATAL: Unrecognised (string) machine option -m%s\n",progname
,optarg
);
2899 fprintf(stderr
,"%s: FATAL error: unrecognised machine option type ID %d\n",progname
,machine_options
[loop
].type
);
2905 if (machine_options
[loop
].name
== 0) {
2906 fprintf(stderr
,"%s: Unrecognised option: -m%s\n",progname
,optarg
);
2913 /* An error message should already have been displayed */
2917 fprintf(stderr
,"%s: FATAL: getopt returned unrecognised code 0x%08X\n",progname
,c
);
2922 if (optind
< argc
) {
2923 fprintf(stderr
,"%s: Spurios non-option arguments ",progname
);
2924 while (optind
< argc
)
2925 fprintf(stderr
,"\"%s\" ",argv
[optind
++]);
2926 fprintf(stderr
,"\n");
2930 if ((features
& FEATURE_FAST
) && (features
& FEATURE_WARNINGS
))
2931 fprintf(stderr
,"Warning: Fast model generation selected, along with trace or warnings.\n");
2933 process_instructions(doarch
,features
) ;
2937 /*---------------------------------------------------------------------------*/
2939 /* We can't assume that the compiler for the build system has strtoul,
2940 so we provide our own copy. */
2943 * Copyright (c) 1990 Regents of the University of California.
2944 * All rights reserved.
2946 * Redistribution and use in source and binary forms, with or without
2947 * modification, are permitted provided that the following conditions
2949 * 1. Redistributions of source code must retain the above copyright
2950 * notice, this list of conditions and the following disclaimer.
2951 * 2. Redistributions in binary form must reproduce the above copyright
2952 * notice, this list of conditions and the following disclaimer in the
2953 * documentation and/or other materials provided with the distribution.
2954 * 3. All advertising materials mentioning features or use of this software
2955 * must display the following acknowledgement:
2956 * This product includes software developed by the University of
2957 * California, Berkeley and its contributors.
2958 * 4. Neither the name of the University nor the names of its contributors
2959 * may be used to endorse or promote products derived from this software
2960 * without specific prior written permission.
2962 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2963 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2964 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2965 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2966 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2967 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2968 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2969 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2970 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2971 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2976 * Convert a string to an unsigned long integer.
2978 * Ignores `locale' stuff. Assumes that the upper and lower case
2979 * alphabets and digits are each contiguous.
2981 static unsigned long
2982 my_strtoul(nptr
, endptr
, base
)
2987 register const char *s
= nptr
;
2988 register unsigned long acc
;
2990 register unsigned long cutoff
;
2991 register int neg
= 0, any
, cutlim
;
2994 * See strtol for comments as to the logic used.
2998 } while (isspace(c
));
3002 } else if (c
== '+')
3004 if ((base
== 0 || base
== 16) &&
3005 c
== '0' && (*s
== 'x' || *s
== 'X')) {
3011 base
= c
== '0' ? 8 : 10;
3012 cutoff
= (unsigned long)ULONG_MAX
/ (unsigned long)base
;
3013 cutlim
= (unsigned long)ULONG_MAX
% (unsigned long)base
;
3014 for (acc
= 0, any
= 0;; c
= *s
++) {
3017 else if (isalpha(c
))
3018 c
-= isupper(c
) ? 'A' - 10 : 'a' - 10;
3023 if (any
< 0 || acc
> cutoff
|| (acc
== cutoff
&& c
> cutlim
))
3037 *endptr
= (char *) (any
? s
- 1 : nptr
);
3041 /*---------------------------------------------------------------------------*/
3043 /*> EOF gencode.c <*/