diff options
Diffstat (limited to 'gcc/config/s390/s390.md')
-rw-r--r-- | gcc/config/s390/s390.md | 373 |
1 files changed, 322 insertions, 51 deletions
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 197aa67ebcb..26be40e5906 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -1,5 +1,5 @@ ;;- Machine description for GNU compiler -- S/390 / zSeries version. -;; Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +;; Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. ;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and ;; Ulrich Weigand (uweigand@de.ibm.com). ;; This file is part of GNU CC. @@ -44,6 +44,34 @@ ;; s_operand -- Matches a valid S operand in a RS, SI or SS type instruction. ;; +;; +;; UNSPEC usage +;; + +(define_constants + [; TLS relocation specifiers + (UNSPEC_TLSGD 500) + (UNSPEC_TLSLDM 501) + (UNSPEC_NTPOFF 502) + (UNSPEC_DTPOFF 503) + (UNSPEC_GOTNTPOFF 504) + (UNSPEC_INDNTPOFF 505) + + ; TLS support + (UNSPEC_TP 510) + (UNSPEC_TLSLDM_NTPOFF 511) + (UNSPEC_TLS_LOAD 512) + ]) + +;; +;; UNSPEC_VOLATILE usage +;; + +(define_constants + [; TLS support + (UNSPECV_SET_TP 500) + ]) + ;; Define an insn type attribute. This is used in function unit delay ;; computations. @@ -500,6 +528,31 @@ "ltr\\t%0,%0" [(set_attr "op_type" "RR")]) +(define_insn "*tsthiCCT" + [(set (reg 33) + (compare (match_operand:HI 0 "nonimmediate_operand" "?Q,d") + (match_operand:HI 1 "const0_operand" ""))) + (set (match_operand:HI 2 "register_operand" "=d,0") + (match_dup 0))] + "s390_match_ccmode(insn, CCTmode)" + "@ + icm\\t%2,3,%0 + tml\\t%0,65535" + [(set_attr "op_type" "RS,RI") + (set_attr "atype" "mem,reg")]) + +(define_insn "*tsthiCCT_cconly" + [(set (reg 33) + (compare (match_operand:HI 0 "nonimmediate_operand" "?Q,d") + (match_operand:HI 1 "const0_operand" ""))) + (clobber (match_scratch:HI 2 "=d,X"))] + "s390_match_ccmode(insn, CCTmode)" + "@ + icm\\t%2,3,%0 + tml\\t%0,65535" + [(set_attr "op_type" "RS,RI") + (set_attr "atype" "mem,reg")]) + (define_insn "*tsthi" [(set (reg 33) (compare (match_operand:HI 0 "s_operand" "Q") @@ -521,6 +574,30 @@ [(set_attr "op_type" "RS") (set_attr "atype" "mem")]) +(define_insn "*tstqiCCT" + [(set (reg 33) + (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,d") + (match_operand:QI 1 "const0_operand" ""))) + (set (match_operand:QI 2 "register_operand" "=d,0") + (match_dup 0))] + "s390_match_ccmode(insn, CCTmode)" + "@ + icm\\t%2,1,%0 + tml\\t%0,255" + [(set_attr "op_type" "RS,RI") + (set_attr "atype" "mem,reg")]) + +(define_insn "*tstqiCCT_cconly" + [(set (reg 33) + (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,d") + (match_operand:QI 1 "const0_operand" "")))] + "s390_match_ccmode(insn, CCTmode)" + "@ + cli\\t%0,0 + tml\\t%0,255" + [(set_attr "op_type" "SI,RI") + (set_attr "atype" "mem,reg")]) + (define_insn "*tstqi" [(set (reg 33) (compare (match_operand:QI 0 "s_operand" "Q") @@ -844,18 +921,15 @@ ; movdi instruction pattern(s). ; -;; If generating PIC code and operands[1] is a symbolic CONST, emit a -;; move to get the address of the symbolic object from the GOT. - (define_expand "movdi" [(set (match_operand:DI 0 "general_operand" "") (match_operand:DI 1 "general_operand" ""))] "" " { - /* Handle PIC symbolic constants. */ - if (TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1])) - emit_pic_move (operands, DImode); + /* Handle symbolic constants. */ + if (TARGET_64BIT && SYMBOLIC_CONST (operands[1])) + emit_symbolic_move (operands); /* During and after reload, we need to force constants to the literal pool ourselves, if necessary. */ @@ -1008,18 +1082,15 @@ ; movsi instruction pattern(s). ; -;; If generating PIC code and operands[1] is a symbolic CONST, emit a -;; move to get the address of the symbolic object from the GOT. - (define_expand "movsi" [(set (match_operand:SI 0 "general_operand" "") (match_operand:SI 1 "general_operand" ""))] "" " { - /* Handle PIC symbolic constants. */ - if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[1])) - emit_pic_move (operands, SImode); + /* Handle symbolic constants. */ + if (!TARGET_64BIT && SYMBOLIC_CONST (operands[1])) + emit_symbolic_move (operands); /* expr.c tries to load an effective address using force_reg. This fails because we don't have a @@ -2837,25 +2908,6 @@ ; adddi3 instruction pattern(s). ; -(define_insn "*la_64_cc" - [(set (match_operand:DI 0 "register_operand" "=d") - (match_operand:QI 1 "address_operand" "p")) - (clobber (reg:CC 33))] - "TARGET_64BIT - && preferred_la_operand_p (operands[1], 1)" - "#" - [(set_attr "op_type" "RX") - (set_attr "atype" "mem") - (set_attr "type" "la")]) - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (match_operand:QI 1 "address_operand" "")) - (clobber (reg:CC 33))] - "TARGET_64BIT && reload_completed - && preferred_la_operand_p (operands[1], 0)" - [(set (match_dup 0) (match_dup 1))]) - (define_insn "*adddi3_sign" [(set (match_operand:DI 0 "register_operand" "=d,d") (plus:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m")) @@ -3025,6 +3077,32 @@ (set_attr "atype" "mem") (set_attr "type" "la")]) +(define_peephole2 + [(parallel + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:QI 1 "address_operand" "")) + (clobber (reg:CC 33))])] + "TARGET_64BIT + && strict_memory_address_p (VOIDmode, operands[1]) + && preferred_la_operand_p (operands[1])" + [(set (match_dup 0) (match_dup 1))] + "") + +(define_peephole2 + [(set (match_operand:DI 0 "register_operand" "") + (match_operand:DI 1 "register_operand" "")) + (parallel + [(set (match_dup 0) + (plus:DI (match_dup 0) + (match_operand:DI 2 "nonmemory_operand" ""))) + (clobber (reg:CC 33))])] + "TARGET_64BIT + && !reg_overlap_mentioned_p (operands[0], operands[2]) + && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (DImode, operands[1], operands[2])) + && preferred_la_operand_p (gen_rtx_PLUS (DImode, operands[1], operands[2]))" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))] + "") + (define_expand "reload_indi" [(parallel [(match_operand:DI 0 "register_operand" "=a") (match_operand:DI 1 "s390_plus_operand" "") @@ -3041,25 +3119,6 @@ ; addsi3 instruction pattern(s). ; -(define_insn "*la_31_cc" - [(set (match_operand:SI 0 "register_operand" "=d") - (match_operand:QI 1 "address_operand" "p")) - (clobber (reg:CC 33))] - "!TARGET_64BIT - && preferred_la_operand_p (operands[1], 1)" - "#" - [(set_attr "op_type" "RX") - (set_attr "atype" "mem") - (set_attr "type" "la")]) - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (match_operand:QI 1 "address_operand" "")) - (clobber (reg:CC 33))] - "!TARGET_64BIT && reload_completed - && preferred_la_operand_p (operands[1], 0)" - [(set (match_dup 0) (match_dup 1))]) - (define_insn "*addsi3_imm_cc" [(set (reg 33) (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "0") @@ -3208,6 +3267,32 @@ (set_attr "atype" "mem") (set_attr "type" "la")]) +(define_peephole2 + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:QI 1 "address_operand" "")) + (clobber (reg:CC 33))])] + "!TARGET_64BIT + && strict_memory_address_p (VOIDmode, operands[1]) + && preferred_la_operand_p (operands[1])" + [(set (match_dup 0) (match_dup 1))] + "") + +(define_peephole2 + [(set (match_operand:SI 0 "register_operand" "") + (match_operand:SI 1 "register_operand" "")) + (parallel + [(set (match_dup 0) + (plus:SI (match_dup 0) + (match_operand:SI 2 "nonmemory_operand" ""))) + (clobber (reg:CC 33))])] + "!TARGET_64BIT + && !reg_overlap_mentioned_p (operands[0], operands[2]) + && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (SImode, operands[1], operands[2])) + && preferred_la_operand_p (gen_rtx_PLUS (SImode, operands[1], operands[2]))" + [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))] + "") + (define_insn "*la_31_and" [(set (match_operand:SI 0 "register_operand" "=d") (and:SI (match_operand:QI 1 "address_operand" "p") @@ -6452,6 +6537,192 @@ (set_attr "type" "jsr") (set_attr "atype" "mem")]) +;; +;;- Thread-local storage support. +;; + +(define_insn "get_tp_64" + [(set (match_operand:DI 0 "nonimmediate_operand" "=??d,Q") + (unspec:DI [(const_int 0)] UNSPEC_TP))] + "TARGET_64BIT" + "@ + ear\\t%0,%%a0\;sllg\\t%0,%0,32\;ear\\t%0,%%a1 + stam\\t%%a0,%%a1,%0" + [(set_attr "op_type" "NN,RS") + (set_attr "atype" "reg,mem") + (set_attr "type" "o3,*") + (set_attr "length" "14,*")]) + +(define_insn "get_tp_31" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,Q") + (unspec:SI [(const_int 0)] UNSPEC_TP))] + "!TARGET_64BIT" + "@ + ear\\t%0,%%a0 + stam\\t%%a0,%%a0,%0" + [(set_attr "op_type" "RRE,RS") + (set_attr "atype" "reg,mem")]) + +(define_insn "set_tp_64" + [(unspec_volatile [(match_operand:DI 0 "general_operand" "??d,Q")] UNSPECV_SET_TP) + (clobber (match_scratch:SI 1 "=d,X"))] + "TARGET_64BIT" + "@ + sar\\t%%a1,%0\;srlg\\t%1,%0,32\;sar\\t%%a0,%1 + lam\\t%%a0,%%a1,%0" + [(set_attr "op_type" "NN,RS") + (set_attr "atype" "reg,mem") + (set_attr "type" "o3,*") + (set_attr "length" "14,*")]) + +(define_insn "set_tp_31" + [(unspec_volatile [(match_operand:SI 0 "general_operand" "d,Q")] UNSPECV_SET_TP)] + "!TARGET_64BIT" + "@ + sar\\t%%a0,%0 + lam\\t%%a0,%%a0,%0" + [(set_attr "op_type" "RRE,RS") + (set_attr "atype" "reg,mem")]) + +(define_insn "*tls_load_64" + [(set (match_operand:DI 0 "register_operand" "=d") + (unspec:DI [(match_operand:DI 1 "memory_operand" "m") + (match_operand:DI 2 "" "")] + UNSPEC_TLS_LOAD))] + "TARGET_64BIT" + "lg\\t%0,%1%J2" + [(set_attr "op_type" "RXE") + (set_attr "atype" "mem")]) + +(define_insn "*tls_load_31" + [(set (match_operand:SI 0 "register_operand" "=d") + (unspec:SI [(match_operand:SI 1 "memory_operand" "m") + (match_operand:SI 2 "" "")] + UNSPEC_TLS_LOAD))] + "!TARGET_64BIT" + "l\\t%0,%1%J2" + [(set_attr "op_type" "RX") + (set_attr "atype" "mem")]) + +(define_expand "call_value_tls" + [(set (match_operand 0 "" "") + (call (const_int 0) (const_int 0))) + (use (match_operand 1 "" ""))] + "" + " +{ + rtx insn, sym; + + if (!flag_pic) + abort (); + + sym = s390_tls_get_offset (); + sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113); + sym = gen_rtx_CONST (Pmode, sym); + + /* Unless we can use the bras(l) insn, force the + routine address into a register. */ + if (!TARGET_SMALL_EXEC && !TARGET_64BIT) + { + rtx target = gen_reg_rtx (Pmode); + emit_move_insn (target, sym); + sym = target; + } + + sym = gen_rtx_MEM (QImode, sym); + + /* Emit insn. */ + insn = emit_call_insn ( + gen_call_value_tls_exp (operands[0], sym, const0_rtx, + gen_rtx_REG (Pmode, RETURN_REGNUM), + operands[1])); + + /* The calling convention of __tls_get_offset uses the + GOT register implicitly. */ + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), operands[0]); + CONST_OR_PURE_CALL_P (insn) = 1; + + DONE; +}") + +(define_expand "call_value_tls_exp" + [(parallel [(set (match_operand 0 "" "") + (call (match_operand 1 "" "") + (match_operand 2 "" ""))) + (clobber (match_operand 3 "" "")) + (use (match_operand 4 "" ""))])] + "" + "") + +(define_insn "brasl_tls" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:DI 1 "bras_sym_operand" "X")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "brasl\\t%3,%1%J4" + [(set_attr "op_type" "RIL") + (set_attr "type" "jsr")]) + +(define_insn "bras_tls" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:SI 1 "bras_sym_operand" "X")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "TARGET_SMALL_EXEC" + "bras\\t%3,%1%J4" + [(set_attr "op_type" "RI") + (set_attr "type" "jsr")]) + +(define_insn "basr_tls_64" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:DI 1 "register_operand" "a")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "basr\\t%3,%1%J4" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr")]) + +(define_insn "basr_tls_31" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:SI 1 "register_operand" "a")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "!TARGET_64BIT" + "basr\\t%3,%1%J4" + [(set_attr "op_type" "RR") + (set_attr "type" "jsr") + (set_attr "atype" "mem")]) + +(define_insn "bas_tls_64" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:QI 1 "address_operand" "p")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:DI 3 "register_operand" "=r")) + (use (match_operand:DI 4 "" ""))] + "TARGET_64BIT" + "bas\\t%3,%a1%J4" + [(set_attr "op_type" "RX") + (set_attr "type" "jsr") + (set_attr "atype" "mem")]) + +(define_insn "bas_tls_31" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:QI (match_operand:QI 1 "address_operand" "p")) + (match_operand:SI 2 "const_int_operand" "n"))) + (clobber (match_operand:SI 3 "register_operand" "=r")) + (use (match_operand:SI 4 "" ""))] + "!TARGET_64BIT" + "bas\\t%3,%a1%J4" + [(set_attr "op_type" "RX") + (set_attr "type" "jsr") + (set_attr "atype" "mem")]) ;; ;;- Miscellaneous instructions. |