• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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