Merge pull request #218 from saper/build-fixes
[envytools.git] / envydis / macro.c
blob8f03ef1d4267283abeb91f8d29dd1addd546b3ee
1 /*
2 * Copyright (C) 2010-2011 Marcelina Koƛcielnicka <mwk@0x04.net>
3 * All Rights Reserved.
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
14 * Software.
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"
28 * Immediate fields
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
43 * Register fields
46 static struct sreg reg_sr[] = {
47 { 0, 0, SR_ZERO },
48 { -1 },
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 = { &reg1_bf, "r", .specials = reg_sr };
54 static struct reg reg2_r = { &reg2_bf, "r", .specials = reg_sr };
55 static struct reg reg3_r = { &reg3_bf, "r", .specials = reg_sr };
56 #define REG1 atomreg, &reg1_r
57 #define REG2 atomreg, &reg2_r
58 #define REG3 atomreg, &reg3_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
69 * the index
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
86 * increment.
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
126 { 0, 0, OOPS },
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 = {
166 tabroot,