2 * Copyright (C) 2010-2011 Marcelina KoĆcielnicka <mwk@0x04.net>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 #include "dis-intern.h"
31 static struct bitfield bfsrcposoff
= { 17, 5 };
32 static struct bitfield bfszoff
= { 22, 5 };
33 static struct bitfield bfdstposoff
= { 27, 5 };
34 static struct rbitfield mimmoff
= { { 14, 18 }, BF_SIGNED
};
35 static struct rbitfield btargoff
= { { 14, 18 }, BF_SIGNED
, .pcrel
= 1 };
36 #define BFSRCPOS atomimm, &bfsrcposoff
37 #define BFDSTPOS atomimm, &bfdstposoff
38 #define BFSZ atomimm, &bfszoff
39 #define MIMM atomrimm, &mimmoff
40 #define BTARG atombtarg, &btargoff
46 static struct sreg reg_sr
[] = {
50 static struct bitfield reg1_bf
= { 8, 3 };
51 static struct bitfield reg2_bf
= { 11, 3 };
52 static struct bitfield reg3_bf
= { 14, 3 };
53 static struct reg reg1_r
= { ®1_bf
, "r", .specials
= reg_sr
};
54 static struct reg reg2_r
= { ®2_bf
, "r", .specials
= reg_sr
};
55 static struct reg reg3_r
= { ®3_bf
, "r", .specials
= reg_sr
};
56 #define REG1 atomreg, ®1_r
57 #define REG2 atomreg, ®2_r
58 #define REG3 atomreg, ®3_r
61 * The Fermi PGRAPH MACRO ISA.
63 * Code space is 0x800 32-bit words long and part of PGRAPH context. Code
64 * addresses are counted in 32-bit words. The MACRO unit sits between PFIFO
65 * and PGRAPH_DISPATCH. It processes the following methods:
67 * - 0x114: set upload address [in words]
68 * - 0x118: upload a single word of code to current upload index, increment
70 * - 0x11c: set binding macro index
71 * - 0x120: bind macro specified by 0x11c to code starting at given address
72 * - 0x3800+i*8: launch macro #i [XXX: check range]
73 * - 0x3804+i*8: send an extra param
74 * - any other: pass through to DISPATCH unchanged
76 * There are 8 GPRs, $r0-$r7, $r0 is hardwired to 0. $r1 is set on launch to
77 * the data sent to the 0x3800+i*8 method that caused the launch. There's
78 * a carry flag for adc and sbb opcodes.
80 * The state also includes "current method address" and "current method
81 * increment". They're both set using various "maddr" ops as listed below -
82 * bits 0-11 of operand are shifted left by 2 and become the method address,
83 * bits 12-17 are shifted left by 2 and become the increment. Other bits
84 * are ignored. A "send" op sends a method specified by the current address
85 * with the param used as data, then increments current address by current
88 * A macro is also allowed to submit method reads. This is done by using
89 * the read op. The operand's bits 0-11 are shifted left by 2 and used as
90 * method address to read.
92 * A macro can also pull extra parameters by the "parm" op and its variations.
93 * "parm" will wait until a 0x3804+i*8 method is submitted from PFIFO and load
94 * its data to the destination. If an unconsumed parameter remains after macro
95 * exits, or if a non-3804 method is submitted while macro is waiting for
96 * a parameter, a trap occurs.
98 * As for flow control, there are branch on zero / non-zero instructions, and
99 * every instruction can be marked with the "exit" modifier which causes the
100 * macro to end. Normal branches and "exit" have delay slots - they don't
101 * actually take effect until the next instruction finishes. Branches also
102 * have "annul" variants which don't have delay slots. Combining "exit" with
103 * a branch is a special case: the exit happens if and only if the branch
104 * is not taken. It's an error to use a branch in a delay slot.
106 * Stuff marked SC below is not actually a separate instruction, just
107 * a special case of a more generic insn.
110 F1(exit
, 7, N("exit"));
112 /* various stuff that can be done to result of arith/logic operations */
113 static struct insn tabdst
[] = {
114 { 0x00000000, 0x00000070, N("parm"), REG1
, N("ign") }, // ignore result, fetch param to REG1
115 { 0x00000010, 0x00000070, N("mov"), REG1
}, // store result to REG1
116 { 0x00000020, 0x00000770, N("maddr") }, // SC
117 { 0x00000020, 0x00000070, N("maddr"), REG1
}, // use result as maddr and store it to REG1
118 { 0x00000030, 0x00000070, N("parm"), REG1
, N("send") }, // send result, then fetch param to REG1
119 { 0x00000040, 0x00000770, N("send") }, // SC
120 { 0x00000040, 0x00000070, N("send"), REG1
}, // send result and store it to REG1
121 { 0x00000050, 0x00000070, N("parm"), REG1
, N("maddr") }, // use result as maddr, then fetch param to REG1
122 { 0x00000060, 0x00000770, N("parmsend"), N("maddr") }, // SC
123 { 0x00000060, 0x00000070, N("parmsend"), N("maddr"), REG1
},// use result as maddr and store it to REG1, then fetch param and send it.
124 { 0x00000070, 0x00000770, N("maddrsend") }, // SC
125 { 0x00000070, 0x00000070, N("maddrsend"), REG1
}, // use result as maddr, then send bits 12-17 of result, then store result to REG1
129 F1(annul
, 5, N("annul")); // if set, delay slot insn is annuled if branch taken [ie. branch behaves as if delay slots didn't exist]
131 static struct insn tabm
[] = {
132 { 0x00000000, 0x003e0007, T(dst
), SESTART
, N("add"), REG2
, REG3
, SEEND
},
133 { 0x00020000, 0x003e0007, T(dst
), SESTART
, N("adc"), REG2
, REG3
, SEEND
},
134 { 0x00040000, 0x003e0007, T(dst
), SESTART
, N("sub"), REG2
, REG3
, SEEND
},
135 { 0x00060000, 0x003e0007, T(dst
), SESTART
, N("sbb"), REG2
, REG3
, SEEND
},
136 { 0x00100000, 0x003e0007, T(dst
), SESTART
, N("xor"), REG2
, REG3
, SEEND
},
137 { 0x00120000, 0x003e0007, T(dst
), SESTART
, N("or"), REG2
, REG3
, SEEND
},
138 { 0x00140000, 0x003e0007, T(dst
), SESTART
, N("and"), REG2
, REG3
, SEEND
},
139 { 0x00160000, 0x003e0007, T(dst
), SESTART
, N("andn"), REG2
, REG3
, SEEND
}, // REG2 & ~REG3
140 { 0x00180000, 0x003e0007, T(dst
), SESTART
, N("nand"), REG2
, REG3
, SEEND
}, // ~(REG2 & REG3)
141 { 0x00000011, 0xffffffff, N("nop") }, // SC
142 { 0x00000091, 0xffffffff }, // SC [just exit]
143 { 0x00000001, 0xfffff87f, N("parm"), REG1
}, // SC
144 { 0x00000001, 0x00003807, T(dst
), MIMM
}, // SC
145 { 0x00000001, 0xffffc007, T(dst
), REG2
}, // SC
146 { 0x00000001, 0x00000007, T(dst
), SESTART
, N("add"), REG2
, MIMM
, SEEND
},
147 // take REG2, replace BFSZ bits starting at BFDSTPOS with BFSZ bits starting at BFSRCPOS in REG3.
148 { 0x00000002, 0x00000007, T(dst
), SESTART
, N("extrinsrt"), REG2
, REG3
, BFSRCPOS
, BFSZ
, BFDSTPOS
, SEEND
},
149 // take BFSZ bits starting at REG2 in REG3, shift left by BFDSTPOS
150 { 0x00000003, 0x00000007, T(dst
), SESTART
, N("extrshl"), REG3
, REG2
, BFSZ
, BFDSTPOS
, SEEND
},
151 // take BFSZ bits starting at BFSRCPOS in REG3, shift left by REG2
152 { 0x00000004, 0x00000007, T(dst
), SESTART
, N("extrshl"), REG3
, BFSRCPOS
, BFSZ
, REG2
, SEEND
},
153 { 0x00000015, 0x00003877, N("read"), REG1
, MIMM
}, // SC
154 { 0x00000015, 0x00000077, N("read"), REG1
, SESTART
, N("add"), REG2
, MIMM
, SEEND
},
155 { 0x00000007, 0x00003817, N("bra"), T(annul
), BTARG
},
156 { 0x00000007, 0x00000017, N("braz"), T(annul
), REG2
, BTARG
},
157 { 0x00000017, 0x00000017, N("branz"), T(annul
), REG2
, BTARG
},
158 { 0, 0, T(dst
), OOPS
, REG2
},
161 static struct insn tabroot
[] = {
162 { 0, 0, OP1B
, T(exit
), T(m
) },
165 struct disisa macro_isa_s
= {