1 /*
2 ===========================================================================
3 Copyright (C) 2009 David S. Miller <davem@davemloft.net>
4
5 This file is part of Quake III Arena source code.
6
7 Quake III Arena source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
11
12 Quake III Arena source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Quake III Arena source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
21 */
22
23 /* This code is based almost entirely upon the vm_powerpc.c code by
24 * Przemyslaw Iskra. All I did was make it work on Sparc :-) -DaveM
25 */
26
27 #include <sys/types.h>
28 #include <sys/mman.h>
29 #include <sys/time.h>
30 #include <time.h>
31 #include <stddef.h>
32
33 #include "vm_local.h"
34 #include "vm_sparc.h"
35
36 /* exit() won't be called but use it because it is marked with noreturn */
37 #define DIE( reason ) \
38 do { \
39 Com_Error(ERR_DROP, "vm_sparc compiler error: " reason "\n"); \
40 exit(1); \
41 } while(0)
42
43 /* Select Length - first value on 32 bits, second on 64 */
44 #ifdef __arch64__
45 #define SL(a, b) (b)
46 #else
47 #define SL(a, b) (a)
48 #endif
49
50 #define rTMP G1
51 #define rVMDATA G2
52 #define rPSTACK G3
53 #define rDATABASE G4
54 #define rDATAMASK G5
55
56 struct sparc_opcode {
57 const char *name;
58 unsigned int opcode;
59 unsigned int mask;
60 unsigned char args[4];
61 #define ARG_NONE 0
62 #define ARG_RS1 1
63 #define ARG_RS2 2
64 #define ARG_RD 3
65 #define ARG_SIMM13 4
66 #define ARG_DISP30 5
67 #define ARG_IMM22 6
68 #define ARG_DISP22 7
69 #define ARG_SWTRAP 8
70 };
71
72 #define ARG_RS1_RS2_RD { ARG_RS1, ARG_RS2, ARG_RD }
73 #define ARG_RS1_SIMM13_RD { ARG_RS1, ARG_SIMM13, ARG_RD }
74 #define ARG_RS1_RS2 { ARG_RS1, ARG_RS2 }
75 #define ARG_RS2_RD { ARG_RS2, ARG_RD }
76
77 #define OP_MASK 0xc0000000
78 #define OP2_MASK 0x01c00000
79 #define OP3_MASK 0x01f80000
80 #define OPF_MASK 0x00003fe0
81
82 #define IMM 0x00002000
83
84 #define FMT1(op) ((op) << 30), OP_MASK
85 #define FMT2(op,op2) ((op) << 30)|((op2)<<22), (OP_MASK | OP2_MASK)
86 #define FMT3(op,op3) ((op) << 30)|((op3)<<19), (OP_MASK | OP3_MASK | IMM)
87 #define FMT3I(op,op3) ((op) << 30)|((op3)<<19)|IMM, (OP_MASK | OP3_MASK | IMM)
88 #define FMT3F(op,op3,opf) ((op) << 30)|((op3)<<19)|((opf)<<5), \
89 (OP_MASK | OP3_MASK | OPF_MASK)
90
91 #define BICC(A,COND) FMT2(0,((A<<7)|(COND<<3)|0x2))
92 #define BFCC(A,COND) FMT2(0,((A<<7)|(COND<<3)|0x6))
93 #define TICC(COND) FMT3I(0,((COND<<6)|0x3a))
94
95 enum sparc_iname {
96 CALL, NOP, SETHI,
97
98 BA, BN, BNE, BE, BG, BLE, BGE, BL, BGU, BLEU, BCC, BCS,
99 BPOS, BNEG, BVC, BVS,
100
101 ADDI, ADD,
102 ANDI, AND,
103 ORI, OR,
104 XORI, XOR,
105 SUBI, SUB,
106 ANDNI, ANDN,
107 ORNI, ORN,
108 XNORI, XNOR,
109
110 UMULI, UMUL,
111 SMULI, SMUL,
112 UDIVI, UDIV,
113 SDIVI, SDIV,
114
115 SUBCCI, SUBCC,
116
117 SLLI, SLL,
118 SRLI, SRL,
119 SRAI, SRA,
120
121 WRI, WR,
122
123 SAVEI, SAVE,
124 RESTOREI, RESTORE,
125
126 TA,
127
128 JMPLI, JMPL,
129
130 LDXI, LDX,
131 LDUWI, LDUW,
132 LDUHI, LDUH,
133 LDUBI, LDUB,
134
135 STXI, STX,
136 STWI, STW,
137 STHI, STH,
138 STBI, STB,
139
140 LDFI, LDF,
141 STFI, STF,
142
143 FADD, FSUB, FCMP, FSTOI, FITOS, FNEG, FDIV, FMUL,
144 FBE, FBNE, FBL, FBGE, FBG, FBLE,
145 };
146
147 #define LDLI SL(LDUWI, LDXI)
148 #define LDL SL(LDUW, LDX)
149 #define STLI SL(STWI, STXI)
150 #define STL SL(STW, STX)
151
152 #define SPARC_NOP 0x01000000
153
154 static const struct sparc_opcode sparc_opcodes[] = {
155 { "call", FMT1(1), { ARG_DISP30 }, },
156 { "nop", SPARC_NOP, 0xffffffff, { ARG_NONE }, }, /* sethi %hi(0), %g0 */
157 { "sethi", FMT2(0,4), { ARG_IMM22, ARG_RD }, },
158 { "ba", BICC(0,8), { ARG_DISP22 }, },
159 { "bn", BICC(0,0), { ARG_DISP22 }, },
160 { "bne", BICC(0,9), { ARG_DISP22 }, },
161 { "be", BICC(0,1), { ARG_DISP22 }, },
162 { "bg", BICC(0,10), { ARG_DISP22 }, },
163 { "ble", BICC(0,2), { ARG_DISP22 }, },
164 { "bge", BICC(0,11), { ARG_DISP22 }, },
165 { "bl", BICC(0,3), { ARG_DISP22 }, },
166 { "bgu", BICC(0,12), { ARG_DISP22 }, },
167 { "bleu", BICC(0,4), { ARG_DISP22 }, },
168 { "bcc", BICC(0,13), { ARG_DISP22 }, },
169 { "bcs", BICC(0,5), { ARG_DISP22 }, },
170 { "bpos", BICC(0,14), { ARG_DISP22 }, },
171 { "bneg", BICC(0,6), { ARG_DISP22 }, },
172 { "bvc", BICC(0,15), { ARG_DISP22 }, },
173 { "bvs", BICC(0,7), { ARG_DISP22 }, },
174
175 { "add", FMT3I(2, 0x00), ARG_RS1_SIMM13_RD, },
176 { "add", FMT3 (2, 0x00), ARG_RS1_RS2_RD, },
177 { "and", FMT3I(2, 0x01), ARG_RS1_SIMM13_RD, },
178 { "and", FMT3 (2, 0x01), ARG_RS1_RS2_RD, },
179 { "or", FMT3I(2, 0x02), ARG_RS1_SIMM13_RD, },
180 { "or", FMT3 (2, 0x02), ARG_RS1_RS2_RD, },
181 { "xor", FMT3I(2, 0x03), ARG_RS1_SIMM13_RD, },
182 { "xor", FMT3 (2, 0x03), ARG_RS1_RS2_RD, },
183 { "sub", FMT3I(2, 0x04), ARG_RS1_SIMM13_RD, },
184 { "sub", FMT3 (2, 0x04), ARG_RS1_RS2_RD, },
185 { "andn", FMT3I(2, 0x05), ARG_RS1_SIMM13_RD, },
186 { "andn", FMT3 (2, 0x05), ARG_RS1_RS2_RD, },
187 { "orn", FMT3I(2, 0x06), ARG_RS1_SIMM13_RD, },
188 { "orn", FMT3 (2, 0x06), ARG_RS1_RS2_RD, },
189 { "xnor", FMT3I(2, 0x07), ARG_RS1_SIMM13_RD, },
190 { "xnor", FMT3 (2, 0x07), ARG_RS1_RS2_RD, },
191
192 { "umul", FMT3I(2, 0x0a), ARG_RS1_SIMM13_RD, },
193 { "umul", FMT3 (2, 0x0a), ARG_RS1_RS2_RD, },
194 { "smul", FMT3I(2, 0x0b), ARG_RS1_SIMM13_RD, },
195 { "smul", FMT3 (2, 0x0b), ARG_RS1_RS2_RD, },
196 { "udiv", FMT3I(2, 0x0e), ARG_RS1_SIMM13_RD, },
197 { "udiv", FMT3 (2, 0x0e), ARG_RS1_RS2_RD, },
198 { "sdiv", FMT3I(2, 0x0f), ARG_RS1_SIMM13_RD, },
199 { "sdiv", FMT3 (2, 0x0f), ARG_RS1_RS2_RD, },
200
201 { "subcc", FMT3I(2, 0x14), ARG_RS1_SIMM13_RD, },
202 { "subcc", FMT3 (2, 0x14), ARG_RS1_RS2_RD, },
203
204 { "sll", FMT3I(2, 0x25), ARG_RS1_SIMM13_RD, },
205 { "sll", FMT3 (2, 0x25), ARG_RS1_RS2_RD, },
206 { "srl", FMT3I(2, 0x26), ARG_RS1_SIMM13_RD, },
207 { "srl", FMT3 (2, 0x26), ARG_RS1_RS2_RD, },
208 { "sra", FMT3I(2, 0x27), ARG_RS1_SIMM13_RD, },
209 { "sra", FMT3 (2, 0x27), ARG_RS1_RS2_RD, },
210
211 { "wr", FMT3I(2, 0x30), ARG_RS1_SIMM13_RD, },
212 { "wr", FMT3 (2, 0x30), ARG_RS1_SIMM13_RD, },
213
214 { "save", FMT3I(2,0x3c), ARG_RS1_SIMM13_RD, },
215 { "save", FMT3 (2,0x3c), ARG_RS1_RS2_RD, },
216 { "restore", FMT3I(2,0x3d), ARG_RS1_SIMM13_RD, },
217 { "restore", FMT3 (2,0x3d), ARG_RS1_RS2_RD, },
218 { "ta", TICC(8), { ARG_SWTRAP, ARG_NONE }, },
219 { "jmpl", FMT3I(2,0x38), ARG_RS1_SIMM13_RD, },
220 { "jmpl", FMT3 (2,0x38), ARG_RS1_RS2_RD, },
221
222 { "ldx", FMT3I(3,0x0b), ARG_RS1_SIMM13_RD, },
223 { "ldx", FMT3 (3,0x0b), ARG_RS1_RS2_RD, },
224 { "lduw", FMT3I(3,0x00), ARG_RS1_SIMM13_RD, },
225 { "lduw", FMT3 (3,0x00), ARG_RS1_RS2_RD, },
226 { "lduh", FMT3I(3,0x02), ARG_RS1_SIMM13_RD, },
227 { "lduh", FMT3 (3,0x02), ARG_RS1_RS2_RD, },
228 { "ldub", FMT3I(3,0x01), ARG_RS1_SIMM13_RD, },
229 { "ldub", FMT3 (3,0x01), ARG_RS1_RS2_RD, },
230
231 { "stx", FMT3I(3,0x0e), ARG_RS1_SIMM13_RD, },
232 { "stx", FMT3 (3,0x0e), ARG_RS1_RS2_RD, },
233 { "stw", FMT3I(3,0x04), ARG_RS1_SIMM13_RD, },
234 { "stw", FMT3 (3,0x04), ARG_RS1_RS2_RD, },
235 { "sth", FMT3I(3,0x06), ARG_RS1_SIMM13_RD, },
236 { "sth", FMT3 (3,0x06), ARG_RS1_RS2_RD, },
237 { "stb", FMT3I(3,0x05), ARG_RS1_SIMM13_RD, },
238 { "stb", FMT3 (3,0x05), ARG_RS1_RS2_RD, },
239
240 { "ldf", FMT3I(3,0x20), ARG_RS1_SIMM13_RD, },
241 { "ldf", FMT3 (3,0x20), ARG_RS1_RS2_RD, },
242 { "stf", FMT3I(3,0x24), ARG_RS1_SIMM13_RD, },
243 { "stf", FMT3 (3,0x24), ARG_RS1_RS2_RD, },
244
245 { "fadd", FMT3F(2,0x34,0x041), ARG_RS1_RS2_RD, },
246 { "fsub", FMT3F(2,0x34,0x045), ARG_RS1_RS2_RD, },
247 { "fcmp", FMT3F(2,0x35,0x051), ARG_RS1_RS2, },
248 { "fstoi", FMT3F(2,0x34,0x0d1), ARG_RS2_RD, },
249 { "fitos", FMT3F(2,0x34,0x0c4), ARG_RS2_RD, },
250
251 { "fneg", FMT3F(2,0x34,0x005), ARG_RS2_RD, },
252 { "fdiv", FMT3F(2,0x34,0x04d), ARG_RS1_RS2_RD, },
253 { "fmul", FMT3F(2,0x34,0x049), ARG_RS1_RS2_RD, },
254
255 { "fbe", BFCC(0,9), { ARG_DISP22 }, },
256 { "fbne", BFCC(0,1), { ARG_DISP22 }, },
257 { "fbl", BFCC(0,4), { ARG_DISP22 }, },
258 { "fbge", BFCC(0,11), { ARG_DISP22 }, },
259 { "fbg", BFCC(0,6), { ARG_DISP22 }, },
260 { "fble", BFCC(0,13), { ARG_DISP22 }, },
261 };
262 #define SPARC_NUM_OPCODES (sizeof(sparc_opcodes) / sizeof(sparc_opcodes[0]))
263
264 #define RS1(X) (((X) & 0x1f) << 14)
265 #define RS2(X) (((X) & 0x1f) << 0)
266 #define RD(X) (((X) & 0x1f) << 25)
267 #define SIMM13(X) (((X) & 0x1fff) << 0)
268 #define IMM22(X) (((X) & 0x3fffff) << 0)
269 #define DISP30(X) ((((X) >> 2) & 0x3fffffff) << 0)
270 #define DISP22(X) ((((X) >> 2) & 0x3fffff) << 0)
271 #define SWTRAP(X) (((X) & 0x7f) << 0)
272
273 #define SIMM13_P(X) ((unsigned int) (X) + 0x1000 < 0x2000)
274
vimm(unsigned int val,int bits,int shift,int sgned,int arg_index)275 static void vimm(unsigned int val, int bits, int shift, int sgned, int arg_index)
276 {
277 unsigned int orig_val = val;
278 int orig_bits = bits;
279
280 if (sgned) {
281 int x = (int) val;
282 if (x < 0)
283 x = -x;
284 val = (unsigned int) x;
285 bits--;
286 }
287 if (val & ~((1U << bits) - 1U)) {
288 Com_Printf("VM ERROR: immediate value 0x%08x out of %d bit range\n",
289 orig_val, orig_bits);
290 DIE("sparc VM bug");
291 }
292 }
293
sparc_assemble(enum sparc_iname iname,const int argc,const int * argv)294 static unsigned int sparc_assemble(enum sparc_iname iname, const int argc, const int *argv)
295 {
296 const struct sparc_opcode *op = &sparc_opcodes[iname];
297 unsigned int insn = op->opcode;
298 int i, flt, rd_flt;
299
300 flt = (op->name[0] == 'f');
301 rd_flt = flt || (op->name[2] == 'f');
302
303 for (i = 0; op->args[i] != ARG_NONE; i++) {
304 int val = argv[i];
305
306 switch (op->args[i]) {
307 case ARG_RS1: insn |= RS1(val); break;
308 case ARG_RS2: insn |= RS2(val); break;
309 case ARG_RD: insn |= RD(val); break;
310 case ARG_SIMM13: insn |= SIMM13(val); vimm(val,13,0,1,i); break;
311 case ARG_DISP30: insn |= DISP30(val); vimm(val,30,0,1,i); break;
312 case ARG_IMM22: insn |= IMM22(val); vimm(val,22,0,0,i); break;
313 case ARG_DISP22: insn |= DISP22(val); vimm(val,22,0,1,i); break;
314 case ARG_SWTRAP: insn |= SWTRAP(val); vimm(val,7,0,0,i); break;
315 }
316 }
317
318 return insn;
319 }
320
321 #define IN(inst, args...) \
322 ({ const int argv[] = { args }; \
323 const int argc = sizeof(argv) / sizeof(argv[0]); \
324 sparc_assemble(inst, argc, argv); \
325 })
326
327 #if 0
328 static void pgreg(int reg_num, int arg_index, int flt)
329 {
330 if (!flt) {
331 const char *fmt[] = { "%g", "%o", "%l", "%i" };
332
333 Com_Printf("%s%s%d",
334 (arg_index ? ", " : ""),
335 fmt[reg_num >> 3], reg_num & 7);
336 } else
337 Com_Printf("%s%%f%d", (arg_index ? ", " : ""), reg_num);
338 }
339
340 static void pimm(unsigned int val, int bits, int shift, int sgned, int arg_index)
341
342 {
343 val >>= shift;
344 val &= ((1 << bits) - 1);
345 if (sgned) {
346 int sval = val << (32 - bits);
347 sval >>= (32 - bits);
348 Com_Printf("%s%d",
349 (arg_index ? ", " : ""), sval);
350 } else
351 Com_Printf("%s0x%08x",
352 (arg_index ? ", " : ""), val);
353 }
354
355 static void sparc_disassemble(unsigned int insn)
356 {
357 int op_idx;
358
359 for (op_idx = 0; op_idx < SPARC_NUM_OPCODES; op_idx++) {
360 const struct sparc_opcode *op = &sparc_opcodes[op_idx];
361 int i, flt, rd_flt;
362
363 if ((insn & op->mask) != op->opcode)
364 continue;
365
366 flt = (op->name[0] == 'f');
367 rd_flt = flt || (op->name[2] == 'f');
368
369 Com_Printf("ASM: %7s\t", op->name);
370 for (i = 0; op->args[i] != ARG_NONE; i++) {
371 switch (op->args[i]) {
372 case ARG_RS1: pgreg((insn >> 14) & 0x1f, i, flt); break;
373 case ARG_RS2: pgreg((insn >> 0) & 0x1f, i, flt); break;
374 case ARG_RD: pgreg((insn >> 25) & 0x1f, i, rd_flt); break;
375 case ARG_SIMM13: pimm(insn, 13, 0, 1, i); break;
376 case ARG_DISP30: pimm(insn, 30, 0, 0, i); break;
377 case ARG_IMM22: pimm(insn, 22, 0, 0, i); break;
378 case ARG_DISP22: pimm(insn, 22, 0, 0, i); break;
379 case ARG_SWTRAP: pimm(insn, 7, 0, 0, i); break;
380 }
381 }
382 Com_Printf("\n");
383 return;
384 }
385 }
386 #endif
387
388 /*
389 * opcode information table:
390 * - length of immediate value
391 * - returned register type
392 * - required register(s) type
393 */
394 #define opImm0 0x0000 /* no immediate */
395 #define opImm1 0x0001 /* 1 byte immadiate value after opcode */
396 #define opImm4 0x0002 /* 4 bytes immediate value after opcode */
397
398 #define opRet0 0x0000 /* returns nothing */
399 #define opRetI 0x0004 /* returns integer */
400 #define opRetF 0x0008 /* returns float */
401 #define opRetIF (opRetI | opRetF) /* returns integer or float */
402
403 #define opArg0 0x0000 /* requires nothing */
404 #define opArgI 0x0010 /* requires integer(s) */
405 #define opArgF 0x0020 /* requires float(s) */
406 #define opArgIF (opArgI | opArgF) /* requires integer or float */
407
408 #define opArg2I 0x0040 /* requires second argument, integer */
409 #define opArg2F 0x0080 /* requires second argument, float */
410 #define opArg2IF (opArg2I | opArg2F) /* requires second argument, integer or float */
411
412 static const unsigned char vm_opInfo[256] =
413 {
414 [OP_UNDEF] = opImm0,
415 [OP_IGNORE] = opImm0,
416 [OP_BREAK] = opImm0,
417 [OP_ENTER] = opImm4,
418 /* OP_LEAVE has to accept floats, they will be converted to ints */
419 [OP_LEAVE] = opImm4 | opRet0 | opArgIF,
420 /* only STORE4 and POP use values from OP_CALL,
421 * no need to convert floats back */
422 [OP_CALL] = opImm0 | opRetI | opArgI,
423 [OP_PUSH] = opImm0 | opRetIF,
424 [OP_POP] = opImm0 | opRet0 | opArgIF,
425 [OP_CONST] = opImm4 | opRetIF,
426 [OP_LOCAL] = opImm4 | opRetI,
427 [OP_JUMP] = opImm0 | opRet0 | opArgI,
428
429 [OP_EQ] = opImm4 | opRet0 | opArgI | opArg2I,
430 [OP_NE] = opImm4 | opRet0 | opArgI | opArg2I,
431 [OP_LTI] = opImm4 | opRet0 | opArgI | opArg2I,
432 [OP_LEI] = opImm4 | opRet0 | opArgI | opArg2I,
433 [OP_GTI] = opImm4 | opRet0 | opArgI | opArg2I,
434 [OP_GEI] = opImm4 | opRet0 | opArgI | opArg2I,
435 [OP_LTU] = opImm4 | opRet0 | opArgI | opArg2I,
436 [OP_LEU] = opImm4 | opRet0 | opArgI | opArg2I,
437 [OP_GTU] = opImm4 | opRet0 | opArgI | opArg2I,
438 [OP_GEU] = opImm4 | opRet0 | opArgI | opArg2I,
439 [OP_EQF] = opImm4 | opRet0 | opArgF | opArg2F,
440 [OP_NEF] = opImm4 | opRet0 | opArgF | opArg2F,
441 [OP_LTF] = opImm4 | opRet0 | opArgF | opArg2F,
442 [OP_LEF] = opImm4 | opRet0 | opArgF | opArg2F,
443 [OP_GTF] = opImm4 | opRet0 | opArgF | opArg2F,
444 [OP_GEF] = opImm4 | opRet0 | opArgF | opArg2F,
445
446 [OP_LOAD1] = opImm0 | opRetI | opArgI,
447 [OP_LOAD2] = opImm0 | opRetI | opArgI,
448 [OP_LOAD4] = opImm0 | opRetIF| opArgI,
449 [OP_STORE1] = opImm0 | opRet0 | opArgI | opArg2I,
450 [OP_STORE2] = opImm0 | opRet0 | opArgI | opArg2I,
451 [OP_STORE4] = opImm0 | opRet0 | opArgIF| opArg2I,
452 [OP_ARG] = opImm1 | opRet0 | opArgIF,
453 [OP_BLOCK_COPY] = opImm4 | opRet0 | opArgI | opArg2I,
454
455 [OP_SEX8] = opImm0 | opRetI | opArgI,
456 [OP_SEX16] = opImm0 | opRetI | opArgI,
457 [OP_NEGI] = opImm0 | opRetI | opArgI,
458 [OP_ADD] = opImm0 | opRetI | opArgI | opArg2I,
459 [OP_SUB] = opImm0 | opRetI | opArgI | opArg2I,
460 [OP_DIVI] = opImm0 | opRetI | opArgI | opArg2I,
461 [OP_DIVU] = opImm0 | opRetI | opArgI | opArg2I,
462 [OP_MODI] = opImm0 | opRetI | opArgI | opArg2I,
463 [OP_MODU] = opImm0 | opRetI | opArgI | opArg2I,
464 [OP_MULI] = opImm0 | opRetI | opArgI | opArg2I,
465 [OP_MULU] = opImm0 | opRetI | opArgI | opArg2I,
466 [OP_BAND] = opImm0 | opRetI | opArgI | opArg2I,
467 [OP_BOR] = opImm0 | opRetI | opArgI | opArg2I,
468 [OP_BXOR] = opImm0 | opRetI | opArgI | opArg2I,
469 [OP_BCOM] = opImm0 | opRetI | opArgI,
470 [OP_LSH] = opImm0 | opRetI | opArgI | opArg2I,
471 [OP_RSHI] = opImm0 | opRetI | opArgI | opArg2I,
472 [OP_RSHU] = opImm0 | opRetI | opArgI | opArg2I,
473 [OP_NEGF] = opImm0 | opRetF | opArgF,
474 [OP_ADDF] = opImm0 | opRetF | opArgF | opArg2F,
475 [OP_SUBF] = opImm0 | opRetF | opArgF | opArg2F,
476 [OP_DIVF] = opImm0 | opRetF | opArgF | opArg2F,
477 [OP_MULF] = opImm0 | opRetF | opArgF | opArg2F,
478 [OP_CVIF] = opImm0 | opRetF | opArgI,
479 [OP_CVFI] = opImm0 | opRetI | opArgF,
480 };
481
482 static const char *opnames[256] = {
483 "OP_UNDEF", "OP_IGNORE", "OP_BREAK", "OP_ENTER", "OP_LEAVE", "OP_CALL",
484 "OP_PUSH", "OP_POP", "OP_CONST", "OP_LOCAL", "OP_JUMP",
485 "OP_EQ", "OP_NE", "OP_LTI", "OP_LEI", "OP_GTI", "OP_GEI",
486 "OP_LTU", "OP_LEU", "OP_GTU", "OP_GEU", "OP_EQF", "OP_NEF",
487 "OP_LTF", "OP_LEF", "OP_GTF", "OP_GEF",
488 "OP_LOAD1", "OP_LOAD2", "OP_LOAD4", "OP_STORE1", "OP_STORE2",
489 "OP_STORE4", "OP_ARG", "OP_BLOCK_COPY",
490 "OP_SEX8", "OP_SEX16",
491 "OP_NEGI", "OP_ADD", "OP_SUB", "OP_DIVI", "OP_DIVU",
492 "OP_MODI", "OP_MODU", "OP_MULI", "OP_MULU", "OP_BAND",
493 "OP_BOR", "OP_BXOR", "OP_BCOM", "OP_LSH", "OP_RSHI", "OP_RSHU",
494 "OP_NEGF", "OP_ADDF", "OP_SUBF", "OP_DIVF", "OP_MULF",
495 "OP_CVIF", "OP_CVFI",
496 };
497
VM_Destroy_Compiled(vm_t * vm)498 static void VM_Destroy_Compiled(vm_t *vm)
499 {
500 if (vm->codeBase) {
501 if (munmap(vm->codeBase, vm->codeLength))
502 Com_Printf(S_COLOR_RED "Memory unmap failed, possible memory leak\n");
503 }
504 vm->codeBase = NULL;
505 }
506
507 typedef struct VM_Data {
508 unsigned int dataLength;
509 unsigned int codeLength;
510 unsigned int *CallThunk;
511 int (*AsmCall)(int, int);
512 void (*BlockCopy)(unsigned int, unsigned int, unsigned int);
513 unsigned int *iPointers;
514 unsigned int data[0];
515 } vm_data_t;
516
517 #ifdef offsetof
518 # define VM_Data_Offset(field) offsetof(vm_data_t, field)
519 #else
520 # define OFFSET(structName, field) \
521 ((void *)&(((structName *)NULL)->field) - NULL)
522 # define VM_Data_Offset(field) OFFSET(vm_data_t, field)
523 #endif
524
525 struct src_insn {
526 unsigned char op;
527 unsigned int i_count;
528
529 union {
530 unsigned int i;
531 signed int si;
532 signed short ss[2];
533 unsigned short us[2];
534 unsigned char b;
535 } arg;
536
537 unsigned char dst_reg_flags;
538 unsigned char src1_reg_flags;
539 unsigned char src2_reg_flags;
540 #define REG_FLAGS_FLOAT 0x1
541
542 struct src_insn *next;
543 };
544
545 struct dst_insn;
546 struct jump_insn {
547 enum sparc_iname jump_iname;
548 int jump_dest_insn;
549 struct dst_insn *parent;
550 struct jump_insn *next;
551 };
552
553 struct dst_insn {
554 struct dst_insn *next;
555
556 unsigned int count;
557 unsigned int i_count;
558
559 struct jump_insn *jump;
560 unsigned int length;
561 unsigned int code[0];
562 };
563
564 #define HUNK_SIZE 29
565 struct data_hunk {
566 struct data_hunk *next;
567 int count;
568 unsigned int data[HUNK_SIZE];
569 };
570
571 struct func_info {
572 struct src_insn *first;
573 struct src_insn *last;
574 int has_call;
575 int need_float_tmp;
576
577 struct src_insn *cached_const;
578
579 int stack_space;
580 int gpr_pos;
581 #define rFIRST(fp) ((fp)->gpr_pos - 1)
582 #define rSECOND(fp) ((fp)->gpr_pos - 2)
583 #define POP_GPR(fp) ((fp)->gpr_pos--)
584 #define PUSH_GPR(fp) ((fp)->gpr_pos++)
585
586 int fpr_pos;
587 #define fFIRST(fp) ((fp)->fpr_pos - 1)
588 #define fSECOND(fp) ((fp)->fpr_pos - 2)
589 #define POP_FPR(fp) ((fp)->fpr_pos--)
590 #define PUSH_FPR(fp) ((fp)->fpr_pos++)
591
592 #define INSN_BUF_SIZE 50
593 unsigned int insn_buf[INSN_BUF_SIZE];
594 int insn_index;
595
596 int saved_icount;
597 int force_emit;
598
599 struct jump_insn *jump_first;
600 struct jump_insn *jump_last;
601
602 struct dst_insn *dst_first;
603 struct dst_insn *dst_last;
604 int dst_count;
605
606 struct dst_insn **dst_by_i_count;
607
608 struct data_hunk *data_first;
609 int data_num;
610 };
611
612 #define THUNK_ICOUNT -1
613
sparc_push_data(struct func_info * const fp,unsigned int val)614 static unsigned int sparc_push_data(struct func_info * const fp, unsigned int val)
615 {
616 struct data_hunk *last, *dp = fp->data_first;
617 int off = 0;
618
619 last = NULL;
620 while (dp) {
621 int i;
622
623 for (i = 0; i < dp->count; i++) {
624 if (dp->data[i] == val) {
625 off += i;
626 return VM_Data_Offset(data[off]);
627 }
628 }
629 off += dp->count;
630 last = dp;
631 dp = dp->next;
632 }
633
634 dp = last;
635 if (!dp || dp->count >= HUNK_SIZE) {
636 struct data_hunk *new = Z_Malloc(sizeof(*new));
637 if (!dp)
638 fp->data_first = new;
639 else
640 dp->next = new;
641 dp = new;
642 dp->count = 0;
643 dp->next = NULL;
644 }
645 dp->data[dp->count++] = val;
646 fp->data_num = off + 1;
647 return VM_Data_Offset(data[off]);
648 }
649
dst_insn_insert_tail(struct func_info * const fp,struct dst_insn * dp)650 static void dst_insn_insert_tail(struct func_info * const fp,
651 struct dst_insn *dp)
652 {
653 if (!fp->dst_first) {
654 fp->dst_first = fp->dst_last = dp;
655 } else {
656 fp->dst_last->next = dp;
657 fp->dst_last = dp;
658 }
659 }
660
jump_insn_insert_tail(struct func_info * const fp,struct jump_insn * jp)661 static void jump_insn_insert_tail(struct func_info * const fp,
662 struct jump_insn *jp)
663 {
664 if (!fp->jump_first) {
665 fp->jump_first = fp->jump_last = jp;
666 } else {
667 fp->jump_last->next = jp;
668 fp->jump_last = jp;
669 }
670 }
671
dst_new(struct func_info * const fp,unsigned int length,struct jump_insn * jp,int insns_size)672 static struct dst_insn *dst_new(struct func_info * const fp, unsigned int length,
673 struct jump_insn *jp, int insns_size)
674 {
675 struct dst_insn *dp = Z_Malloc(sizeof(struct dst_insn) + insns_size);
676
677 dp->length = length;
678 dp->jump = jp;
679 dp->count = fp->dst_count++;
680 dp->i_count = fp->saved_icount;
681 dp->next = NULL;
682 if (fp->saved_icount != THUNK_ICOUNT)
683 fp->dst_by_i_count[fp->saved_icount] = dp;
684
685 return dp;
686 }
687
dst_insn_append(struct func_info * const fp)688 static void dst_insn_append(struct func_info * const fp)
689 {
690 int insns_size = (sizeof(unsigned int) * fp->insn_index);
691 struct dst_insn *dp;
692
693 dp = dst_new(fp, fp->insn_index, NULL, insns_size);
694 if (insns_size)
695 memcpy(&dp->code[0], fp->insn_buf, insns_size);
696 dst_insn_insert_tail(fp, dp);
697
698 fp->insn_index = 0;
699 }
700
jump_insn_append(struct func_info * const fp,enum sparc_iname iname,int dest)701 static void jump_insn_append(struct func_info * const fp, enum sparc_iname iname, int dest)
702 {
703 struct jump_insn *jp = Z_Malloc(sizeof(*jp));
704 struct dst_insn *dp;
705
706 dp = dst_new(fp, 2, jp, 0);
707
708 jp->jump_iname = iname;
709 jp->jump_dest_insn = dest;
710 jp->parent = dp;
711 jp->next = NULL;
712
713 jump_insn_insert_tail(fp, jp);
714 dst_insn_insert_tail(fp, dp);
715 }
716
start_emit(struct func_info * const fp,int i_count)717 static void start_emit(struct func_info * const fp, int i_count)
718 {
719 fp->saved_icount = i_count;
720 fp->insn_index = 0;
721 fp->force_emit = 0;
722 }
723
__do_emit_one(struct func_info * const fp,unsigned int insn)724 static void __do_emit_one(struct func_info * const fp, unsigned int insn)
725 {
726 fp->insn_buf[fp->insn_index++] = insn;
727 }
728
729 #define in(inst, args...) __do_emit_one(fp, IN(inst, args))
730
end_emit(struct func_info * const fp)731 static void end_emit(struct func_info * const fp)
732 {
733 if (fp->insn_index || fp->force_emit)
734 dst_insn_append(fp);
735 }
736
emit_jump(struct func_info * const fp,enum sparc_iname iname,int dest)737 static void emit_jump(struct func_info * const fp, enum sparc_iname iname, int dest)
738 {
739 end_emit(fp);
740 jump_insn_append(fp, iname, dest);
741 }
742
analyze_function(struct func_info * const fp)743 static void analyze_function(struct func_info * const fp)
744 {
745 struct src_insn *value_provider[20] = { NULL };
746 struct src_insn *sp = fp->first;
747 int opstack_depth = 0;
748
749 while ((sp = sp->next) != NULL) {
750 unsigned char opi, op = sp->op;
751
752 opi = vm_opInfo[op];
753 if (opi & opArgIF) {
754 struct src_insn *vp = value_provider[--opstack_depth];
755 unsigned char vpopi = vm_opInfo[vp->op];
756
757 if ((opi & opArgI) && (vpopi & opRetI)) {
758 /* src1 and dst are integers */
759 } else if ((opi & opArgF) && (vpopi & opRetF)) {
760 /* src1 and dst are floats */
761 vp->dst_reg_flags |= REG_FLAGS_FLOAT;
762 sp->src1_reg_flags = REG_FLAGS_FLOAT;
763 } else {
764 /* illegal combination */
765 DIE("unrecognized instruction combination");
766 }
767 }
768 if (opi & opArg2IF) {
769 struct src_insn *vp = value_provider[--opstack_depth];
770 unsigned char vpopi = vm_opInfo[vp->op];
771
772 if ((opi & opArg2I) && (vpopi & opRetI)) {
773 /* src2 and dst are integers */
774 } else if ( (opi & opArg2F) && (vpopi & opRetF) ) {
775 /* src2 and dst are floats */
776 vp->dst_reg_flags |= REG_FLAGS_FLOAT;
777 sp->src2_reg_flags = REG_FLAGS_FLOAT;
778 } else {
779 /* illegal combination */
780 DIE("unrecognized instruction combination");
781 }
782 }
783 if (opi & opRetIF) {
784 value_provider[opstack_depth] = sp;
785 opstack_depth++;
786 }
787 }
788 }
789
asmcall(int call,int pstack)790 static int asmcall(int call, int pstack)
791 {
792 vm_t *savedVM = currentVM;
793 int i, ret;
794
795 currentVM->programStack = pstack - 4;
796 if (sizeof(intptr_t) == sizeof(int)) {
797 intptr_t *argPosition = (intptr_t *)((byte *)currentVM->dataBase + pstack + 4);
798 argPosition[0] = -1 - call;
799 ret = currentVM->systemCall(argPosition);
800 } else {
801 intptr_t args[11];
802
803 args[0] = -1 - call;
804 int *argPosition = (int *)((byte *)currentVM->dataBase + pstack + 4);
805 for( i = 1; i < 11; i++ )
806 args[i] = argPosition[i];
807
808 ret = currentVM->systemCall(args);
809 }
810
811 currentVM = savedVM;
812
813 return ret;
814 }
815
blockcopy(unsigned int dest,unsigned int src,unsigned int count)816 static void blockcopy(unsigned int dest, unsigned int src, unsigned int count)
817 {
818 unsigned int dataMask = currentVM->dataMask;
819
820 if ((dest & dataMask) != dest ||
821 (src & dataMask) != src ||
822 ((dest+count) & dataMask) != dest + count ||
823 ((src+count) & dataMask) != src + count) {
824 DIE("OP_BLOCK_COPY out of range!");
825 }
826
827 memcpy(currentVM->dataBase+dest, currentVM->dataBase+src, count);
828 }
829
do_emit_const(struct func_info * const fp,struct src_insn * sp)830 static void do_emit_const(struct func_info * const fp, struct src_insn *sp)
831 {
832 start_emit(fp, sp->i_count);
833 if (sp->dst_reg_flags & REG_FLAGS_FLOAT) {
834 in(LDFI, rVMDATA, sparc_push_data(fp, sp->arg.i), fFIRST(fp));
835 } else {
836 if ((sp->arg.i & ~0x3ff) == 0) {
837 in(ORI, G0, sp->arg.i & 0x3ff, rFIRST(fp));
838 } else if ((sp->arg.i & 0x3ff) == 0) {
839 in(SETHI, sp->arg.i >> 10, rFIRST(fp));
840 } else {
841 in(SETHI, sp->arg.i >> 10, rFIRST(fp));
842 in(ORI, rFIRST(fp), sp->arg.i & 0x3ff, rFIRST(fp));
843 }
844 }
845 end_emit(fp);
846 }
847
848 #define MAYBE_EMIT_CONST(fp) \
849 do { if ((fp)->cached_const) { \
850 int saved_i_count = (fp)->saved_icount; \
851 do_emit_const(fp, (fp)->cached_const); \
852 (fp)->saved_icount = saved_i_count; \
853 } \
854 } while (0)
855
856 #define EMIT_FALSE_CONST(fp) \
857 do { int saved_i_count = (fp)->saved_icount; \
858 (fp)->saved_icount = (fp)->cached_const->i_count; \
859 dst_insn_append(fp); \
860 (fp)->saved_icount = saved_i_count; \
861 } while (0)
862
compile_one_insn(struct func_info * const fp,struct src_insn * sp)863 static void compile_one_insn(struct func_info * const fp, struct src_insn *sp)
864 {
865 start_emit(fp, sp->i_count);
866
867 switch (sp->op) {
868 default:
869 Com_Printf("VM: Unhandled opcode 0x%02x[%s]\n",
870 sp->op,
871 opnames[sp->op] ? opnames[sp->op] : "UNKNOWN");
872 DIE("Unsupported opcode");
873 break;
874
875 case OP_ENTER: {
876 int stack = SL(64, 128);
877
878 if (fp->need_float_tmp)
879 stack += 16;
880
881 in(SAVEI, O6, -stack, O6);
882 if (!SIMM13_P(sp->arg.si)) {
883 in(SETHI, sp->arg.i >> 10, rTMP);
884 in(ORI, rTMP, sp->arg.i & 0x3ff, rTMP);
885 in(SUB, rPSTACK, rTMP, rPSTACK);
886 } else
887 in(SUBI, rPSTACK, sp->arg.si, rPSTACK);
888 break;
889 }
890 case OP_LEAVE:
891 if (fp->cached_const && SIMM13_P(fp->cached_const->arg.si)) {
892 EMIT_FALSE_CONST(fp);
893 if (fp->cached_const->src1_reg_flags & REG_FLAGS_FLOAT)
894 DIE("constant float in OP_LEAVE");
895
896 if (!SIMM13_P(sp->arg.si)) {
897 in(SETHI, sp->arg.i >> 10, rTMP);
898 in(ORI, rTMP, sp->arg.i & 0x3ff, rTMP);
899 in(ADD, rPSTACK, rTMP, rPSTACK);
900 } else
901 in(ADDI, rPSTACK, sp->arg.si, rPSTACK);
902 in(JMPLI, I7, 8, G0);
903 in(RESTOREI, G0, fp->cached_const->arg.si, O0);
904 POP_GPR(fp);
905 } else {
906 MAYBE_EMIT_CONST(fp);
907 if (!SIMM13_P(sp->arg.si)) {
908 in(SETHI, sp->arg.i >> 10, rTMP);
909 in(ORI, rTMP, sp->arg.i & 0x3ff, rTMP);
910 in(ADD, rPSTACK, rTMP, rPSTACK);
911 } else
912 in(ADDI, rPSTACK, sp->arg.si, rPSTACK);
913 if (sp->src1_reg_flags & REG_FLAGS_FLOAT) {
914 in(STFI, O6, SL(64, 128), fFIRST(fp));
915 in(LDUWI, O6, SL(64, 128), O0);
916 in(JMPLI, I7, 8, G0);
917 in(RESTORE, O0, G0, O0);
918 POP_FPR(fp);
919 } else {
920 in(JMPLI, I7, 8, G0);
921 in(RESTORE, rFIRST(fp), G0, O0);
922 POP_GPR(fp);
923 }
924 }
925 assert(fp->gpr_pos == L0);
926 assert(fp->fpr_pos == F0);
927 break;
928 case OP_JUMP:
929 if (fp->cached_const) {
930 EMIT_FALSE_CONST(fp);
931 emit_jump(fp, BA, fp->cached_const->arg.i);
932 } else {
933 MAYBE_EMIT_CONST(fp);
934 in(LDLI, rVMDATA, VM_Data_Offset(iPointers), rTMP);
935 in(SLLI, rFIRST(fp), 2, rFIRST(fp));
936 in(LDL, rTMP, rFIRST(fp), rTMP);
937 in(JMPL, rTMP, G0, G0);
938 in(NOP);
939 }
940 POP_GPR(fp);
941 break;
942 case OP_CALL:
943 if (fp->cached_const) {
944 EMIT_FALSE_CONST(fp);
945 if (fp->cached_const->arg.si >= 0) {
946 emit_jump(fp, CALL, fp->cached_const->arg.i);
947 } else {
948 in(LDLI, rVMDATA, VM_Data_Offset(CallThunk), rTMP);
949 in(LDLI, rVMDATA, VM_Data_Offset(AsmCall), O3);
950 in(ORI, G0, fp->cached_const->arg.si, O0);
951 in(JMPL, rTMP, G0, O7);
952 in(OR, G0, rPSTACK, O1);
953 }
954 in(OR, G0, O0, rFIRST(fp));
955 } else {
956 MAYBE_EMIT_CONST(fp);
957 in(SUBCCI, rFIRST(fp), 0, G0);
958 in(BL, +4*7);
959 in(NOP);
960
961 /* normal call */
962 in(LDLI, rVMDATA, VM_Data_Offset(iPointers), O5);
963 in(SLLI, rFIRST(fp), 2, rFIRST(fp));
964 in(LDL, O5, rFIRST(fp), rTMP);
965 in(BA, +4*4);
966 in(NOP);
967
968 /* syscall */
969 in(LDLI, rVMDATA, VM_Data_Offset(CallThunk), rTMP);
970 in(LDLI, rVMDATA, VM_Data_Offset(AsmCall), O3);
971
972 in(OR, G0, rFIRST(fp), O0);
973 in(JMPL, rTMP, G0, O7);
974 in(OR, G0, rPSTACK, O1);
975
976 /* return value */
977 in(OR, G0, O0, rFIRST(fp));
978 }
979 break;
980 case OP_BLOCK_COPY:
981 MAYBE_EMIT_CONST(fp);
982 in(LDLI, rVMDATA, VM_Data_Offset(CallThunk), rTMP);
983 in(LDLI, rVMDATA, VM_Data_Offset(BlockCopy), O3);
984 in(OR, G0, rSECOND(fp), O0);
985 in(OR, G0, rFIRST(fp), O1);
986 if ((sp->arg.i & ~0x3ff) == 0) {
987 in(ORI, G0, sp->arg.i & 0x3ff, O2);
988 } else if ((sp->arg.i & 0x3ff) == 0) {
989 in(SETHI, sp->arg.i >> 10, O2);
990 } else {
991 in(SETHI, sp->arg.i >> 10, O2);
992 in(ORI, O2, sp->arg.i & 0x3ff, O2);
993 }
994 in(JMPL, rTMP, G0, O7);
995 in(NOP);
996 POP_GPR(fp);
997 POP_GPR(fp);
998 break;
999
1000 case OP_PUSH:
1001 MAYBE_EMIT_CONST(fp);
1002 if (sp->dst_reg_flags & REG_FLAGS_FLOAT)
1003 PUSH_FPR(fp);
1004 else
1005 PUSH_GPR(fp);
1006 fp->force_emit = 1;
1007 break;
1008 case OP_POP:
1009 MAYBE_EMIT_CONST(fp);
1010 if (sp->src1_reg_flags & REG_FLAGS_FLOAT)
1011 POP_FPR(fp);
1012 else
1013 POP_GPR(fp);
1014 fp->force_emit = 1;
1015 break;
1016 case OP_ARG:
1017 MAYBE_EMIT_CONST(fp);
1018 in(ADDI, rPSTACK, sp->arg.b, rTMP);
1019 if (sp->src1_reg_flags & REG_FLAGS_FLOAT) {
1020 in(STF, rDATABASE, rTMP, fFIRST(fp));
1021 POP_FPR(fp);
1022 } else {
1023 in(STW, rDATABASE, rTMP, rFIRST(fp));
1024 POP_GPR(fp);
1025 }
1026 break;
1027 case OP_IGNORE:
1028 MAYBE_EMIT_CONST(fp);
1029 in(NOP);
1030 break;
1031 case OP_BREAK:
1032 MAYBE_EMIT_CONST(fp);
1033 in(TA, 0x5);
1034 break;
1035 case OP_LOCAL:
1036 MAYBE_EMIT_CONST(fp);
1037 PUSH_GPR(fp);
1038 if (!SIMM13_P(sp->arg.i)) {
1039 in(SETHI, sp->arg.i >> 10, rTMP);
1040 in(ORI, rTMP, sp->arg.i & 0x3ff, rTMP);
1041 in(ADD, rPSTACK, rTMP, rFIRST(fp));
1042 } else
1043 in(ADDI, rPSTACK, sp->arg.i, rFIRST(fp));
1044 break;
1045 case OP_CONST:
1046 MAYBE_EMIT_CONST(fp);
1047 break;
1048 case OP_LOAD4:
1049 MAYBE_EMIT_CONST(fp);
1050 in(AND, rFIRST(fp), rDATAMASK, rFIRST(fp));
1051 if (sp->dst_reg_flags & REG_FLAGS_FLOAT) {
1052 PUSH_FPR(fp);
1053 in(LDF, rFIRST(fp), rDATABASE, fFIRST(fp));
1054 POP_GPR(fp);
1055 } else {
1056 in(LDUW, rFIRST(fp), rDATABASE, rFIRST(fp));
1057 }
1058 break;
1059 case OP_LOAD2:
1060 MAYBE_EMIT_CONST(fp);
1061 in(AND, rFIRST(fp), rDATAMASK, rFIRST(fp));
1062 in(LDUH, rFIRST(fp), rDATABASE, rFIRST(fp));
1063 break;
1064 case OP_LOAD1:
1065 MAYBE_EMIT_CONST(fp);
1066 in(AND, rFIRST(fp), rDATAMASK, rFIRST(fp));
1067 in(LDUB, rFIRST(fp), rDATABASE, rFIRST(fp));
1068 break;
1069 case OP_STORE4:
1070 MAYBE_EMIT_CONST(fp);
1071 if (sp->src1_reg_flags & REG_FLAGS_FLOAT) {
1072 in(AND, rFIRST(fp), rDATAMASK, rFIRST(fp));
1073 in(STF, rFIRST(fp), rDATABASE, fFIRST(fp));
1074 POP_FPR(fp);
1075 } else {
1076 in(AND, rSECOND(fp), rDATAMASK, rSECOND(fp));
1077 in(STW, rSECOND(fp), rDATABASE, rFIRST(fp));
1078 POP_GPR(fp);
1079 }
1080 POP_GPR(fp);
1081 break;
1082 case OP_STORE2:
1083 MAYBE_EMIT_CONST(fp);
1084 in(AND, rSECOND(fp), rDATAMASK, rSECOND(fp));
1085 in(STH, rSECOND(fp), rDATABASE, rFIRST(fp));
1086 POP_GPR(fp);
1087 POP_GPR(fp);
1088 break;
1089 case OP_STORE1:
1090 MAYBE_EMIT_CONST(fp);
1091 in(AND, rSECOND(fp), rDATAMASK, rSECOND(fp));
1092 in(STB, rSECOND(fp), rDATABASE, rFIRST(fp));
1093 POP_GPR(fp);
1094 POP_GPR(fp);
1095 break;
1096 case OP_EQ:
1097 case OP_NE:
1098 case OP_LTI:
1099 case OP_GEI:
1100 case OP_GTI:
1101 case OP_LEI:
1102 case OP_LTU:
1103 case OP_GEU:
1104 case OP_GTU:
1105 case OP_LEU: {
1106 enum sparc_iname iname = BA;
1107
1108 if (fp->cached_const && SIMM13_P(fp->cached_const->arg.si)) {
1109 EMIT_FALSE_CONST(fp);
1110 in(SUBCCI, rSECOND(fp), fp->cached_const->arg.si, G0);
1111 } else {
1112 MAYBE_EMIT_CONST(fp);
1113 in(SUBCC, rSECOND(fp), rFIRST(fp), G0);
1114 }
1115 switch(sp->op) {
1116 case OP_EQ: iname = BE; break;
1117 case OP_NE: iname = BNE; break;
1118 case OP_LTI: iname = BL; break;
1119 case OP_GEI: iname = BGE; break;
1120 case OP_GTI: iname = BG; break;
1121 case OP_LEI: iname = BLE; break;
1122 case OP_LTU: iname = BCS; break;
1123 case OP_GEU: iname = BCC; break;
1124 case OP_GTU: iname = BGU; break;
1125 case OP_LEU: iname = BLEU; break;
1126 }
1127 emit_jump(fp, iname, sp->arg.i);
1128 POP_GPR(fp);
1129 POP_GPR(fp);
1130 break;
1131 }
1132
1133 case OP_SEX8:
1134 MAYBE_EMIT_CONST(fp);
1135 in(SLLI, rFIRST(fp), 24, rFIRST(fp));
1136 in(SRAI, rFIRST(fp), 24, rFIRST(fp));
1137 break;
1138 case OP_SEX16:
1139 MAYBE_EMIT_CONST(fp);
1140 in(SLLI, rFIRST(fp), 16, rFIRST(fp));
1141 in(SRAI, rFIRST(fp), 16, rFIRST(fp));
1142 break;
1143 case OP_NEGI:
1144 MAYBE_EMIT_CONST(fp);
1145 in(SUB, G0, rFIRST(fp), rFIRST(fp));
1146 break;
1147 case OP_ADD:
1148 if (fp->cached_const && SIMM13_P(fp->cached_const->arg.si)) {
1149 EMIT_FALSE_CONST(fp);
1150 in(ADDI, rSECOND(fp), fp->cached_const->arg.si, rSECOND(fp));
1151 } else {
1152 MAYBE_EMIT_CONST(fp);
1153 in(ADD, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1154 }
1155 POP_GPR(fp);
1156 break;
1157 case OP_SUB:
1158 if (fp->cached_const && SIMM13_P(fp->cached_const->arg.si)) {
1159 EMIT_FALSE_CONST(fp);
1160 in(SUBI, rSECOND(fp), fp->cached_const->arg.si, rSECOND(fp));
1161 } else {
1162 MAYBE_EMIT_CONST(fp);
1163 in(SUB, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1164 }
1165 POP_GPR(fp);
1166 break;
1167 case OP_DIVI:
1168 MAYBE_EMIT_CONST(fp);
1169 in(SRAI, rSECOND(fp), 31, rTMP);
1170 in(WRI, rTMP, 0, Y_REG);
1171 in(SDIV, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1172 POP_GPR(fp);
1173 break;
1174 case OP_DIVU:
1175 MAYBE_EMIT_CONST(fp);
1176 in(WRI, G0, 0, Y_REG);
1177 in(UDIV, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1178 POP_GPR(fp);
1179 break;
1180 case OP_MODI:
1181 MAYBE_EMIT_CONST(fp);
1182 in(SRAI, rSECOND(fp), 31, rTMP);
1183 in(WRI, rTMP, 0, Y_REG);
1184 in(SDIV, rSECOND(fp), rFIRST(fp), rTMP);
1185 in(SMUL, rTMP, rFIRST(fp), rTMP);
1186 in(SUB, rSECOND(fp), rTMP, rSECOND(fp));
1187 POP_GPR(fp);
1188 break;
1189 case OP_MODU:
1190 MAYBE_EMIT_CONST(fp);
1191 in(WRI, G0, 0, Y_REG);
1192 in(UDIV, rSECOND(fp), rFIRST(fp), rTMP);
1193 in(SMUL, rTMP, rFIRST(fp), rTMP);
1194 in(SUB, rSECOND(fp), rTMP, rSECOND(fp));
1195 POP_GPR(fp);
1196 break;
1197 case OP_MULI:
1198 MAYBE_EMIT_CONST(fp);
1199 in(SMUL, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1200 POP_GPR(fp);
1201 break;
1202 case OP_MULU:
1203 MAYBE_EMIT_CONST(fp);
1204 in(UMUL, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1205 POP_GPR(fp);
1206 break;
1207 case OP_BAND:
1208 MAYBE_EMIT_CONST(fp);
1209 in(AND, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1210 POP_GPR(fp);
1211 break;
1212 case OP_BOR:
1213 MAYBE_EMIT_CONST(fp);
1214 in(OR, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1215 POP_GPR(fp);
1216 break;
1217 case OP_BXOR:
1218 MAYBE_EMIT_CONST(fp);
1219 in(XOR, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1220 POP_GPR(fp);
1221 break;
1222 case OP_BCOM:
1223 MAYBE_EMIT_CONST(fp);
1224 in(XNOR, rFIRST(fp), G0, rFIRST(fp));
1225 break;
1226 case OP_LSH:
1227 if (fp->cached_const) {
1228 EMIT_FALSE_CONST(fp);
1229 in(SLLI, rSECOND(fp), fp->cached_const->arg.si, rSECOND(fp));
1230 } else {
1231 MAYBE_EMIT_CONST(fp);
1232 in(SLL, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1233 }
1234 POP_GPR(fp);
1235 break;
1236 case OP_RSHI:
1237 if (fp->cached_const) {
1238 EMIT_FALSE_CONST(fp);
1239 in(SRAI, rSECOND(fp), fp->cached_const->arg.si, rSECOND(fp));
1240 } else {
1241 MAYBE_EMIT_CONST(fp);
1242 in(SRA, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1243 }
1244 POP_GPR(fp);
1245 break;
1246 case OP_RSHU:
1247 if (fp->cached_const) {
1248 EMIT_FALSE_CONST(fp);
1249 in(SRLI, rSECOND(fp), fp->cached_const->arg.si, rSECOND(fp));
1250 } else {
1251 MAYBE_EMIT_CONST(fp);
1252 in(SRL, rSECOND(fp), rFIRST(fp), rSECOND(fp));
1253 }
1254 POP_GPR(fp);
1255 break;
1256
1257 case OP_NEGF:
1258 MAYBE_EMIT_CONST(fp);
1259 in(FNEG, fFIRST(fp), fFIRST(fp));
1260 break;
1261 case OP_ADDF:
1262 MAYBE_EMIT_CONST(fp);
1263 in(FADD, fSECOND(fp), fFIRST(fp), fSECOND(fp));
1264 POP_FPR(fp);
1265 break;
1266 case OP_SUBF:
1267 MAYBE_EMIT_CONST(fp);
1268 in(FSUB, fSECOND(fp), fFIRST(fp), fSECOND(fp));
1269 POP_FPR(fp);
1270 break;
1271 case OP_DIVF:
1272 MAYBE_EMIT_CONST(fp);
1273 in(FDIV, fSECOND(fp), fFIRST(fp), fSECOND(fp));
1274 POP_FPR(fp);
1275 break;
1276 case OP_MULF:
1277 MAYBE_EMIT_CONST(fp);
1278 in(FMUL, fSECOND(fp), fFIRST(fp), fSECOND(fp));
1279 POP_FPR(fp);
1280 break;
1281
1282 case OP_EQF:
1283 case OP_NEF:
1284 case OP_LTF:
1285 case OP_GEF:
1286 case OP_GTF:
1287 case OP_LEF: {
1288 enum sparc_iname iname = FBE;
1289
1290 MAYBE_EMIT_CONST(fp);
1291 in(FCMP, fSECOND(fp), fFIRST(fp));
1292 switch(sp->op) {
1293 case OP_EQF: iname = FBE; break;
1294 case OP_NEF: iname = FBNE; break;
1295 case OP_LTF: iname = FBL; break;
1296 case OP_GEF: iname = FBGE; break;
1297 case OP_GTF: iname = FBG; break;
1298 case OP_LEF: iname = FBLE; break;
1299 }
1300 emit_jump(fp, iname, sp->arg.i);
1301 POP_FPR(fp);
1302 POP_FPR(fp);
1303 break;
1304 }
1305 case OP_CVIF:
1306 MAYBE_EMIT_CONST(fp);
1307 PUSH_FPR(fp);
1308 in(STWI, O6, SL(64, 128), rFIRST(fp));
1309 in(LDFI, O6, SL(64, 128), fFIRST(fp));
1310 in(FITOS, fFIRST(fp), fFIRST(fp));
1311 POP_GPR(fp);
1312 break;
1313 case OP_CVFI:
1314 MAYBE_EMIT_CONST(fp);
1315 PUSH_GPR(fp);
1316 in(FSTOI, fFIRST(fp), fFIRST(fp));
1317 in(STFI, O6, SL(64, 128), fFIRST(fp));
1318 in(LDUWI, O6, SL(64, 128), rFIRST(fp));
1319 POP_FPR(fp);
1320 break;
1321 }
1322 if (sp->op != OP_CONST) {
1323 fp->cached_const = NULL;
1324 end_emit(fp);
1325 } else {
1326 fp->cached_const = sp;
1327 if (sp->dst_reg_flags & REG_FLAGS_FLOAT) {
1328 PUSH_FPR(fp);
1329 } else {
1330 PUSH_GPR(fp);
1331 }
1332 }
1333 end_emit(fp);
1334 }
1335
free_source_insns(struct func_info * const fp)1336 static void free_source_insns(struct func_info * const fp)
1337 {
1338 struct src_insn *sp = fp->first->next;
1339
1340 while (sp) {
1341 struct src_insn *next = sp->next;
1342 Z_Free(sp);
1343 sp = next;
1344 }
1345 }
1346
compile_function(struct func_info * const fp)1347 static void compile_function(struct func_info * const fp)
1348 {
1349 struct src_insn *sp;
1350
1351 analyze_function(fp);
1352
1353 fp->gpr_pos = L0;
1354 fp->fpr_pos = F0;
1355 fp->insn_index = 0;
1356
1357 fp->stack_space = SL(64, 128);
1358 fp->cached_const = NULL;
1359
1360 sp = fp->first;
1361 while ((sp = sp->next) != NULL)
1362 compile_one_insn(fp, sp);
1363
1364 free_source_insns(fp);
1365 }
1366
1367 /* We have two thunks for sparc. The first is for the entry into
1368 * the VM, where setup the fixed global registers. The second is
1369 * for calling out to C code from the VM, where we need to preserve
1370 * those fixed globals across the call.
1371 */
emit_vm_thunk(struct func_info * const fp)1372 static void emit_vm_thunk(struct func_info * const fp)
1373 {
1374 /* int vm_thunk(void *vmdata, int programstack, void *database, int datamask) */
1375 start_emit(fp, THUNK_ICOUNT);
1376
1377 in(OR, G0, O0, rVMDATA);
1378 in(OR, G0, O1, rPSTACK);
1379 in(OR, G0, O2, rDATABASE);
1380 in(BA, +4*17);
1381 in(OR, G0, O3, rDATAMASK);
1382
1383 /* int call_thunk(int arg0, int arg1, int arg2, int (*func)(int int int)) */
1384 #define CALL_THUNK_INSN_OFFSET 5
1385 in(SAVEI, O6, -SL(64, 128), O6);
1386
1387 in(OR, G0, rVMDATA, L0);
1388 in(OR, G0, rPSTACK, L1);
1389 in(OR, G0, rDATABASE, L2);
1390 in(OR, G0, rDATAMASK, L3);
1391
1392 in(OR, G0, I0, O0);
1393 in(OR, G0, I1, O1);
1394 in(JMPL, I3, G0, O7);
1395 in(OR, G0, I2, O2);
1396
1397 in(OR, G0, L0, rVMDATA);
1398 in(OR, G0, L1, rPSTACK);
1399 in(OR, G0, L2, rDATABASE);
1400 in(OR, G0, L3, rDATAMASK);
1401
1402 in(JMPLI, I7, 8, G0);
1403 in(RESTORE, O0, G0, O0);
1404
1405 end_emit(fp);
1406 }
1407
sparc_compute_code(vm_t * vm,struct func_info * const fp)1408 static void sparc_compute_code(vm_t *vm, struct func_info * const fp)
1409 {
1410 struct dst_insn *dp = fp->dst_first;
1411 unsigned int *code_now, *code_begin;
1412 unsigned char *data_and_code;
1413 unsigned int code_length;
1414 int code_insns = 0, off;
1415 struct data_hunk *dhp;
1416 struct jump_insn *jp;
1417 vm_data_t *data;
1418
1419 while (dp) {
1420 code_insns += dp->length;
1421 dp = dp->next;
1422 }
1423
1424 code_length = (sizeof(vm_data_t) +
1425 (fp->data_num * sizeof(unsigned int)) +
1426 (code_insns * sizeof(unsigned int)));
1427
1428 data_and_code = mmap(NULL, code_length, PROT_READ | PROT_WRITE,
1429 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
1430 if (!data_and_code)
1431 DIE("Not enough memory");
1432
1433 code_now = code_begin = (unsigned int *)
1434 (data_and_code + VM_Data_Offset(data[fp->data_num]));
1435
1436 dp = fp->dst_first;
1437 while (dp) {
1438 int i_count = dp->i_count;
1439
1440 if (i_count != THUNK_ICOUNT) {
1441 if (!fp->dst_by_i_count[i_count])
1442 fp->dst_by_i_count[i_count] = (void *) code_now;
1443 }
1444 if (!dp->jump) {
1445 memcpy(code_now, &dp->code[0], dp->length * sizeof(unsigned int));
1446 code_now += dp->length;
1447 } else {
1448 int i;
1449
1450 dp->jump->parent = (void *) code_now;
1451
1452 for (i = 0; i < dp->length; i++)
1453 code_now[i] = SPARC_NOP;
1454 code_now += dp->length;
1455 }
1456
1457 dp = dp->next;
1458 }
1459
1460 jp = fp->jump_first;
1461 while (jp) {
1462 unsigned int *from = (void *) jp->parent;
1463 unsigned int *to = (void *) fp->dst_by_i_count[jp->jump_dest_insn];
1464 signed int disp = (to - from);
1465
1466 *from = IN(jp->jump_iname, disp << 2);
1467
1468 jp = jp->next;
1469 }
1470
1471 vm->codeBase = data_and_code;
1472 vm->codeLength = code_length;
1473
1474 data = (vm_data_t *) data_and_code;
1475 data->CallThunk = code_begin + CALL_THUNK_INSN_OFFSET;
1476 data->AsmCall = asmcall;
1477 data->BlockCopy = blockcopy;
1478 data->iPointers = (unsigned int *) vm->instructionPointers;
1479 data->dataLength = VM_Data_Offset(data[fp->data_num]);
1480 data->codeLength = (code_now - code_begin) * sizeof(unsigned int);
1481
1482 #if 0
1483 {
1484 unsigned int *insn = code_begin;
1485 int i;
1486
1487 Com_Printf("INSN DUMP\n");
1488 for (i = 0; i < data->codeLength / 4; i+= 8) {
1489 Com_Printf("\t.word\t0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
1490 insn[i + 0], insn[i + 1],
1491 insn[i + 2], insn[i + 3],
1492 insn[i + 4], insn[i + 5],
1493 insn[i + 6], insn[i + 7]);
1494 }
1495 }
1496 #endif
1497
1498 dhp = fp->data_first;
1499 off = 0;
1500 while (dhp) {
1501 struct data_hunk *next = dhp->next;
1502 int i;
1503
1504 for (i = 0; i < dhp->count; i++)
1505 data->data[off + i] = dhp->data[i];
1506
1507 off += dhp->count;
1508
1509 Z_Free(dhp);
1510
1511 dhp = next;
1512 }
1513 fp->data_first = NULL;
1514 fp->data_num = 0;
1515
1516 dp = fp->dst_first;
1517 while (dp) {
1518 struct dst_insn *next = dp->next;
1519 if (dp->jump)
1520 Z_Free(dp->jump);
1521 Z_Free(dp);
1522 dp = next;
1523 }
1524 fp->dst_first = fp->dst_last = NULL;
1525 }
1526
VM_Compile(vm_t * vm,vmHeader_t * header)1527 void VM_Compile(vm_t *vm, vmHeader_t *header)
1528 {
1529 struct func_info fi;
1530 unsigned char *code;
1531 int i_count, pc, i;
1532
1533 memset(&fi, 0, sizeof(fi));
1534
1535 fi.first = Z_Malloc(sizeof(struct src_insn));
1536 fi.first->next = NULL;
1537
1538 #ifdef __arch64__
1539 Z_Free(vm->instructionPointers);
1540 vm->instructionPointers = Z_Malloc(header->instructionCount *
1541 sizeof(void *));
1542 #endif
1543
1544 fi.dst_by_i_count = (struct dst_insn **) vm->instructionPointers;
1545 memset(fi.dst_by_i_count, 0, header->instructionCount * sizeof(void *));
1546
1547 vm->compiled = qfalse;
1548
1549 emit_vm_thunk(&fi);
1550
1551 code = (unsigned char *) header + header->codeOffset;
1552 pc = 0;
1553
1554 for (i_count = 0; i_count < header->instructionCount; i_count++) {
1555 unsigned char opi, op = code[pc++];
1556 struct src_insn *sp;
1557
1558 if (op == OP_CALL || op == OP_BLOCK_COPY)
1559 fi.has_call = 1;
1560 opi = vm_opInfo[op];
1561 if (op == OP_CVIF || op == OP_CVFI ||
1562 (op == OP_LEAVE && (opi & opArgF)))
1563 fi.need_float_tmp = 1;
1564
1565 if (op == OP_ENTER) {
1566 if (fi.first->next)
1567 compile_function(&fi);
1568 fi.first->next = NULL;
1569 fi.last = fi.first;
1570 fi.has_call = fi.need_float_tmp = 0;
1571 }
1572
1573 sp = Z_Malloc(sizeof(*sp));
1574 sp->op = op;
1575 sp->i_count = i_count;
1576 sp->arg.i = 0;
1577 sp->next = NULL;
1578
1579 if (vm_opInfo[op] & opImm4) {
1580 union {
1581 unsigned char b[4];
1582 unsigned int i;
1583 } c = { { code[ pc + 3 ], code[ pc + 2 ],
1584 code[ pc + 1 ], code[ pc + 0 ] }, };
1585
1586 sp->arg.i = c.i;
1587 pc += 4;
1588 } else if (vm_opInfo[op] & opImm1) {
1589 sp->arg.b = code[pc++];
1590 }
1591
1592 fi.last->next = sp;
1593 fi.last = sp;
1594 }
1595 compile_function(&fi);
1596
1597 Z_Free(fi.first);
1598
1599 memset(fi.dst_by_i_count, 0, header->instructionCount * sizeof(void *));
1600 sparc_compute_code(vm, &fi);
1601
1602 for (i = 0; i < header->instructionCount; i++) {
1603 if (!fi.dst_by_i_count[i]) {
1604 Com_Printf(S_COLOR_RED "Pointer %d not initialized !\n", i);
1605 DIE("sparc JIT bug");
1606 }
1607 }
1608
1609 if (mprotect(vm->codeBase, vm->codeLength, PROT_READ|PROT_EXEC)) {
1610 VM_Destroy_Compiled(vm);
1611 DIE("mprotect failed");
1612 }
1613
1614 vm->destroy = VM_Destroy_Compiled;
1615 vm->compiled = qtrue;
1616 }
1617
VM_CallCompiled(vm_t * vm,int * args)1618 int VM_CallCompiled(vm_t *vm, int *args)
1619 {
1620 vm_data_t *vm_dataAndCode = (void *) vm->codeBase;
1621 int programStack = vm->programStack;
1622 int stackOnEntry = programStack;
1623 byte *image = vm->dataBase;
1624 int *argPointer;
1625 int retVal;
1626
1627 currentVM = vm;
1628
1629 vm->currentlyInterpreting = qtrue;
1630
1631 programStack -= 48;
1632 argPointer = (int *)&image[ programStack + 8 ];
1633 memcpy( argPointer, args, 4 * 9 );
1634 argPointer[-1] = 0;
1635 argPointer[-2] = -1;
1636
1637 /* call generated code */
1638 {
1639 int (*entry)(void *, int, void *, int);
1640 entry = (void *)(vm->codeBase + vm_dataAndCode->dataLength);
1641 retVal = entry(vm->codeBase, programStack, vm->dataBase, vm->dataMask);
1642 }
1643
1644 vm->programStack = stackOnEntry;
1645 vm->currentlyInterpreting = qfalse;
1646
1647 return retVal;
1648 }
1649