1 /* -*- mode: C; c-basic-offset: 3; -*- */
2
3 /*---------------------------------------------------------------*/
4 /*--- begin host_s390_defs.h ---*/
5 /*---------------------------------------------------------------*/
6
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
10
11 Copyright IBM Corp. 2010-2011
12
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29 */
30
31 /* Contributed by Florian Krohm */
32
33 #ifndef __VEX_HOST_S390_DEFS_H
34 #define __VEX_HOST_S390_DEFS_H
35
36 #include "libvex_basictypes.h" /* Bool */
37 #include "libvex.h" /* VexArchInfo */
38 #include "main_util.h" /* needed for host_generic_regs.h */
39 #include "host_generic_regs.h" /* HReg */
40
41 /* --------- Registers --------- */
42 const HChar *s390_hreg_as_string(HReg);
43
44 /* Dedicated registers */
45 HReg s390_hreg_guest_state_pointer(void);
46
47
48 /* Given the index of a function argument, return the number of the
49 general purpose register in which it is being passed. Arguments are
50 counted 0, 1, 2, ... and they are being passed in r2, r3, r4, ... */
51 static __inline__ unsigned
s390_gprno_from_arg_index(unsigned ix)52 s390_gprno_from_arg_index(unsigned ix)
53 {
54 return ix + 2;
55 }
56
57 /* --------- Memory address expressions (amodes). --------- */
58
59 /* These are the address modes:
60 (1) b12: base register + 12-bit unsigned offset (e.g. RS)
61 (2) b20: base register + 20-bit signed offset (e.g. RSY)
62 (3) bx12: base register + index register + 12-bit unsigned offset (e.g. RX)
63 (4) bx20: base register + index register + 20-bit signed offset (e.g. RXY)
64 fixs390: There is also pc-relative stuff.. e.g. LARL
65 */
66
67 typedef enum {
68 S390_AMODE_B12,
69 S390_AMODE_B20,
70 S390_AMODE_BX12,
71 S390_AMODE_BX20
72 } s390_amode_t;
73
74 typedef struct {
75 s390_amode_t tag;
76 HReg b;
77 HReg x; /* hregNumber(x) == 0 for S390_AMODE_B12/B20 kinds */
78 Int d; /* 12 bit unsigned or 20 bit signed */
79 } s390_amode;
80
81
82 s390_amode *s390_amode_b12(Int d, HReg b);
83 s390_amode *s390_amode_b20(Int d, HReg b);
84 s390_amode *s390_amode_bx12(Int d, HReg b, HReg x);
85 s390_amode *s390_amode_bx20(Int d, HReg b, HReg x);
86 s390_amode *s390_amode_for_guest_state(Int d);
87 Bool s390_amode_is_sane(const s390_amode *);
88
89 const HChar *s390_amode_as_string(const s390_amode *);
90
91 /* ------------- 2nd (right) operand of binary operation ---------------- */
92
93 typedef enum {
94 S390_OPND_REG,
95 S390_OPND_IMMEDIATE,
96 S390_OPND_AMODE
97 } s390_opnd_t;
98
99
100 /* Naming convention for operand locations:
101 R - GPR
102 I - immediate value
103 M - memory (any Amode may be used)
104 */
105
106 /* An operand that is either in a GPR or is addressable via a BX20 amode */
107 typedef struct {
108 s390_opnd_t tag;
109 union {
110 HReg reg;
111 s390_amode *am;
112 ULong imm;
113 } variant;
114 } s390_opnd_RMI;
115
116
117 /* The kind of instructions */
118 typedef enum {
119 S390_INSN_LOAD, /* load register from memory */
120 S390_INSN_STORE, /* store register to memory */
121 S390_INSN_MOVE, /* from register to register */
122 S390_INSN_COND_MOVE, /* conditonal "move" to register */
123 S390_INSN_LOAD_IMMEDIATE,
124 S390_INSN_ALU,
125 S390_INSN_MUL, /* n-bit operands; 2n-bit result */
126 S390_INSN_DIV, /* 2n-bit dividend; n-bit divisor; n-bit quot/rem */
127 S390_INSN_DIVS, /* n-bit dividend; n-bit divisor; n-bit quot/rem */
128 S390_INSN_CLZ, /* count left-most zeroes */
129 S390_INSN_UNOP,
130 S390_INSN_TEST, /* test operand and set cc */
131 S390_INSN_CC2BOOL,/* convert condition code to 0/1 */
132 S390_INSN_COMPARE,
133 S390_INSN_BRANCH, /* un/conditional goto */
134 S390_INSN_HELPER_CALL,
135 S390_INSN_CAS, /* compare and swap */
136 S390_INSN_BFP_BINOP, /* Binary floating point 32-bit / 64-bit */
137 S390_INSN_BFP_UNOP,
138 S390_INSN_BFP_TRIOP,
139 S390_INSN_BFP_COMPARE,
140 S390_INSN_BFP128_BINOP, /* Binary floating point 128-bit */
141 S390_INSN_BFP128_UNOP,
142 S390_INSN_BFP128_COMPARE,
143 S390_INSN_BFP128_CONVERT_TO,
144 S390_INSN_BFP128_CONVERT_FROM,
145 S390_INSN_MFENCE
146 } s390_insn_tag;
147
148
149 /* The kind of ALU instructions */
150 typedef enum {
151 S390_ALU_ADD,
152 S390_ALU_SUB,
153 S390_ALU_MUL, /* n-bit operands; result is lower n-bit of product */
154 S390_ALU_AND,
155 S390_ALU_OR,
156 S390_ALU_XOR,
157 S390_ALU_LSH,
158 S390_ALU_RSH,
159 S390_ALU_RSHA /* arithmetic */
160 } s390_alu_t;
161
162
163 /* The kind of unary integer operations */
164 typedef enum {
165 S390_ZERO_EXTEND_8,
166 S390_ZERO_EXTEND_16,
167 S390_ZERO_EXTEND_32,
168 S390_SIGN_EXTEND_8,
169 S390_SIGN_EXTEND_16,
170 S390_SIGN_EXTEND_32,
171 S390_NEGATE
172 } s390_unop_t;
173
174 /* The kind of ternary BFP operations */
175 typedef enum {
176 S390_BFP_MADD,
177 S390_BFP_MSUB,
178 } s390_bfp_triop_t;
179
180 /* The kind of binary BFP operations */
181 typedef enum {
182 S390_BFP_ADD,
183 S390_BFP_SUB,
184 S390_BFP_MUL,
185 S390_BFP_DIV
186 } s390_bfp_binop_t;
187
188
189 /* The kind of unary BFP operations */
190 typedef enum {
191 S390_BFP_ABS,
192 S390_BFP_NABS,
193 S390_BFP_NEG,
194 S390_BFP_SQRT,
195 S390_BFP_I32_TO_F32,
196 S390_BFP_I32_TO_F64,
197 S390_BFP_I32_TO_F128,
198 S390_BFP_I64_TO_F32,
199 S390_BFP_I64_TO_F64,
200 S390_BFP_I64_TO_F128,
201 S390_BFP_F32_TO_I32,
202 S390_BFP_F32_TO_I64,
203 S390_BFP_F32_TO_F64,
204 S390_BFP_F32_TO_F128,
205 S390_BFP_F64_TO_I32,
206 S390_BFP_F64_TO_I64,
207 S390_BFP_F64_TO_F32,
208 S390_BFP_F64_TO_F128,
209 S390_BFP_F128_TO_I32,
210 S390_BFP_F128_TO_I64,
211 S390_BFP_F128_TO_F32,
212 S390_BFP_F128_TO_F64
213 } s390_bfp_unop_t;
214
215
216 /* Condition code. The encoding of the enumerators matches the value of
217 the mask field in the various branch opcodes. */
218 typedef enum {
219 S390_CC_NEVER= 0,
220 S390_CC_OVFL = 1, /* overflow */
221 S390_CC_H = 2, /* A > B ; high */
222 S390_CC_NLE = 3, /* not low or equal */
223 S390_CC_L = 4, /* A < B ; low */
224 S390_CC_NHE = 5, /* not high or equal */
225 S390_CC_LH = 6, /* low or high */
226 S390_CC_NE = 7, /* A != B ; not zero */
227 S390_CC_E = 8, /* A == B ; zero */
228 S390_CC_NLH = 9, /* not low or high */
229 S390_CC_HE = 10, /* A >= B ; high or equal*/
230 S390_CC_NL = 11, /* not low */
231 S390_CC_LE = 12, /* A <= B ; low or equal */
232 S390_CC_NH = 13, /* not high */
233 S390_CC_NO = 14, /* not overflow */
234 S390_CC_ALWAYS = 15
235 } s390_cc_t;
236
237
238 /* Rounding mode as it is encoded in the m3/m4 fields of certain
239 instructions (e.g. CFEBR) */
240 typedef enum {
241 /* S390_ROUND_NEAREST_AWAY = 1, not supported */
242 S390_ROUND_NEAREST_EVEN = 4,
243 S390_ROUND_ZERO = 5,
244 S390_ROUND_POSINF = 6,
245 S390_ROUND_NEGINF = 7
246 } s390_round_t;
247
248
249 /* Invert the condition code */
250 static __inline__ s390_cc_t
s390_cc_invert(s390_cc_t cond)251 s390_cc_invert(s390_cc_t cond)
252 {
253 return S390_CC_ALWAYS - cond;
254 }
255
256
257 typedef struct {
258 s390_insn_tag tag;
259 UChar size; /* size of the result in bytes */
260 union {
261 struct {
262 HReg dst;
263 s390_amode *src;
264 } load;
265 struct {
266 s390_amode *dst;
267 HReg src;
268 } store;
269 struct {
270 HReg dst;
271 HReg src;
272 } move;
273 struct {
274 s390_cc_t cond;
275 HReg dst;
276 s390_opnd_RMI src;
277 } cond_move;
278 struct {
279 HReg dst;
280 ULong value; /* not sign extended */
281 } load_immediate;
282 /* add, and, or, xor */
283 struct {
284 s390_alu_t tag;
285 HReg dst; /* op1 */
286 s390_opnd_RMI op2;
287 } alu;
288 struct {
289 Bool signed_multiply;
290 HReg dst_hi; /* r10 */
291 HReg dst_lo; /* also op1 r11 */
292 s390_opnd_RMI op2;
293 } mul;
294 struct {
295 Bool signed_divide;
296 HReg op1_hi; /* also remainder r10 */
297 HReg op1_lo; /* also quotient r11 */
298 s390_opnd_RMI op2;
299 } div;
300 struct {
301 HReg rem; /* remainder r10 */
302 HReg op1; /* also quotient r11 */
303 s390_opnd_RMI op2;
304 } divs;
305 struct {
306 HReg num_bits; /* number of leftmost '0' bits r10 */
307 HReg clobber; /* unspecified r11 */
308 s390_opnd_RMI src;
309 } clz;
310 struct {
311 s390_unop_t tag;
312 HReg dst;
313 s390_opnd_RMI src;
314 } unop;
315 struct {
316 Bool signed_comparison;
317 HReg src1;
318 s390_opnd_RMI src2;
319 } compare;
320 struct {
321 HReg dst; /* condition code in s390 encoding */
322 HReg op1;
323 HReg op2;
324 } bfp_compare;
325 struct {
326 s390_opnd_RMI src;
327 } test;
328 /* Convert the condition code to a boolean value. */
329 struct {
330 s390_cc_t cond;
331 HReg dst;
332 } cc2bool;
333 struct {
334 HReg op1;
335 s390_amode *op2;
336 HReg op3;
337 HReg old_mem;
338 } cas;
339 struct {
340 IRJumpKind kind;
341 s390_cc_t cond;
342 s390_opnd_RMI dst;
343 } branch;
344 /* Pseudo-insn for representing a helper call.
345 TARGET is the absolute address of the helper function
346 NUM_ARGS says how many arguments are being passed.
347 All arguments have integer type and are being passed according to ABI,
348 i.e. in registers r2, r3, r4, r5, and r6, with argument #0 being
349 passed in r2 and so forth. */
350 struct {
351 s390_cc_t cond;
352 Addr64 target;
353 UInt num_args;
354 HChar *name; /* callee's name (for debugging) */
355 } helper_call;
356 struct {
357 s390_bfp_triop_t tag;
358 s390_round_t rounding_mode;
359 HReg dst; /* first operand */
360 HReg op2; /* second operand */
361 HReg op3; /* third operand */
362 } bfp_triop;
363 struct {
364 s390_bfp_binop_t tag;
365 s390_round_t rounding_mode;
366 HReg dst; /* left operand */
367 HReg op2; /* right operand */
368 } bfp_binop;
369 struct {
370 s390_bfp_unop_t tag;
371 s390_round_t rounding_mode;
372 HReg dst; /* result */
373 HReg op; /* operand */
374 } bfp_unop;
375 struct {
376 s390_bfp_binop_t tag;
377 s390_round_t rounding_mode;
378 HReg dst_hi; /* left operand; high part */
379 HReg dst_lo; /* left operand; low part */
380 HReg op2_hi; /* right operand; high part */
381 HReg op2_lo; /* right operand; low part */
382 } bfp128_binop;
383 /* This variant is also used by the BFP128_CONVERT_TO and
384 BFP128_CONVERT_FROM insns. */
385 struct {
386 s390_bfp_unop_t tag;
387 s390_round_t rounding_mode;
388 HReg dst_hi; /* result; high part */
389 HReg dst_lo; /* result; low part */
390 HReg op_hi; /* operand; high part */
391 HReg op_lo; /* operand; low part */
392 } bfp128_unop;
393 struct {
394 HReg dst; /* condition code in s390 encoding */
395 HReg op1_hi; /* left operand; high part */
396 HReg op1_lo; /* left operand; low part */
397 HReg op2_hi; /* right operand; high part */
398 HReg op2_lo; /* right operand; low part */
399 } bfp128_compare;
400 } variant;
401 } s390_insn;
402
403 s390_insn *s390_insn_load(UChar size, HReg dst, s390_amode *src);
404 s390_insn *s390_insn_store(UChar size, s390_amode *dst, HReg src);
405 s390_insn *s390_insn_move(UChar size, HReg dst, HReg src);
406 s390_insn *s390_insn_cond_move(UChar size, s390_cc_t cond, HReg dst,
407 s390_opnd_RMI src);
408 s390_insn *s390_insn_load_immediate(UChar size, HReg dst, ULong val);
409 s390_insn *s390_insn_alu(UChar size, s390_alu_t, HReg dst,
410 s390_opnd_RMI op2);
411 s390_insn *s390_insn_mul(UChar size, HReg dst_hi, HReg dst_lo,
412 s390_opnd_RMI op2, Bool signed_multiply);
413 s390_insn *s390_insn_div(UChar size, HReg op1_hi, HReg op1_lo,
414 s390_opnd_RMI op2, Bool signed_divide);
415 s390_insn *s390_insn_divs(UChar size, HReg rem, HReg op1, s390_opnd_RMI op2);
416 s390_insn *s390_insn_clz(UChar size, HReg num_bits, HReg clobber,
417 s390_opnd_RMI op);
418 s390_insn *s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3,
419 HReg old);
420 s390_insn *s390_insn_unop(UChar size, s390_unop_t tag, HReg dst,
421 s390_opnd_RMI opnd);
422 s390_insn *s390_insn_cc2bool(HReg dst, s390_cc_t src);
423 s390_insn *s390_insn_test(UChar size, s390_opnd_RMI src);
424 s390_insn *s390_insn_compare(UChar size, HReg dst, s390_opnd_RMI opnd,
425 Bool signed_comparison);
426 s390_insn *s390_insn_branch(IRJumpKind jk, s390_cc_t cond, s390_opnd_RMI dst);
427 s390_insn *s390_insn_helper_call(s390_cc_t cond, Addr64 target, UInt num_args,
428 HChar *name);
429 s390_insn *s390_insn_bfp_triop(UChar size, s390_bfp_triop_t, HReg dst, HReg op2,
430 HReg op3, s390_round_t);
431 s390_insn *s390_insn_bfp_binop(UChar size, s390_bfp_binop_t, HReg dst, HReg op2,
432 s390_round_t);
433 s390_insn *s390_insn_bfp_unop(UChar size, s390_bfp_unop_t tag, HReg dst,
434 HReg op, s390_round_t);
435 s390_insn *s390_insn_bfp_compare(UChar size, HReg dst, HReg op1, HReg op2);
436 s390_insn *s390_insn_bfp128_binop(UChar size, s390_bfp_binop_t, HReg dst_hi,
437 HReg dst_lo, HReg op2_hi, HReg op2_lo,
438 s390_round_t);
439 s390_insn *s390_insn_bfp128_unop(UChar size, s390_bfp_unop_t, HReg dst_hi,
440 HReg dst_lo, HReg op_hi, HReg op_lo,
441 s390_round_t);
442 s390_insn *s390_insn_bfp128_compare(UChar size, HReg dst, HReg op1_hi,
443 HReg op1_lo, HReg op2_hi, HReg op2_lo);
444 s390_insn *s390_insn_bfp128_convert_to(UChar size, s390_bfp_unop_t,
445 HReg dst_hi, HReg dst_lo, HReg op);
446 s390_insn *s390_insn_bfp128_convert_from(UChar size, s390_bfp_unop_t,
447 HReg dst, HReg op_hi, HReg op_lo,
448 s390_round_t);
449 s390_insn *s390_insn_mfence(void);
450 UInt s390_insn_emit(UChar *buf, Int nbuf, const s390_insn *insn,
451 void *dispatch);
452
453 const HChar *s390_insn_as_string(const s390_insn *);
454
455 /*--------------------------------------------------------*/
456 /* --- Interface exposed to VEX --- */
457 /*--------------------------------------------------------*/
458
459 void ppS390AMode(s390_amode *);
460 void ppS390Instr(s390_insn *, Bool mode64);
461 void ppHRegS390(HReg);
462
463 /* Some functions that insulate the register allocator from details
464 of the underlying instruction set. */
465 void getRegUsage_S390Instr( HRegUsage *, s390_insn *, Bool );
466 void mapRegs_S390Instr ( HRegRemap *, s390_insn *, Bool );
467 Bool isMove_S390Instr ( s390_insn *, HReg *, HReg * );
468 Int emit_S390Instr ( UChar *, Int, s390_insn *, Bool,
469 void *, void * );
470 void getAllocableRegs_S390( Int *, HReg **, Bool );
471 void genSpill_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
472 void genReload_S390 ( HInstr **, HInstr **, HReg , Int , Bool );
473 s390_insn *directReload_S390 ( s390_insn *, HReg, Short );
474 HInstrArray *iselSB_S390 ( IRSB *, VexArch, VexArchInfo *, VexAbiInfo * );
475
476 /* KLUDGE: See detailled comment in host_s390_defs.c. */
477 extern const VexArchInfo *s390_archinfo_host;
478
479 /* Convenience macros to test installed facilities */
480 #define s390_host_has_ldisp \
481 (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_LDISP))
482 #define s390_host_has_eimm \
483 (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_EIMM))
484 #define s390_host_has_gie \
485 (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_GIE))
486 #define s390_host_has_dfp \
487 (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_DFP))
488 #define s390_host_has_fgx \
489 (s390_archinfo_host->hwcaps & (VEX_HWCAPS_S390X_FGX))
490
491 #endif /* ndef __VEX_HOST_S390_DEFS_H */
492
493 /*---------------------------------------------------------------*/
494 /*--- end host_s390_defs.h ---*/
495 /*---------------------------------------------------------------*/
496