From 2bb7a0f55b929b09ae3b1fb72ffdda42f766f0aa Mon Sep 17 00:00:00 2001 From: Richard Stallman Date: Sat, 15 Feb 1992 21:27:49 +0000 Subject: [PATCH] *** empty log message *** From-SVN: r328 --- gcc/config/i386/i386.md | 287 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 258 insertions(+), 29 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 70f2224c8f1..95b3adbdab2 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -206,6 +206,9 @@ "TARGET_80387" "") +;; The `ble' and `blt' patterns can reverse a compare, so we must allow +;; an immediate operand as operand 0 in the recognizers below. + (define_insn "" [(set (cc0) (compare (match_operand:DF 0 "general_operand" "f") @@ -356,9 +359,24 @@ ;; General case of fullword move. +;; 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" ""))] + "" + " +{ + extern int flag_pic; + + if (flag_pic && SYMBOLIC_CONST (operands[1])) + emit_pic_move (operands, SImode); +}") + ;; On i486, incl reg is faster than movl $1,reg. -(define_insn "movsi" +(define_insn "" [(set (match_operand:SI 0 "general_operand" "=g,r") (match_operand:SI 1 "general_operand" "ri,m"))] "" @@ -1490,10 +1508,10 @@ ;; Remainder instructions. (define_insn "divmodsi4" - [(set (match_operand:SI 0 "general_operand" "=a") - (div:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "register_operand" "=a") + (div:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rm"))) - (set (match_operand:SI 3 "general_operand" "=&d") + (set (match_operand:SI 3 "register_operand" "=&d") (mod:SI (match_dup 1) (match_dup 2)))] "" "* @@ -1507,20 +1525,20 @@ }") (define_insn "divmodhi4" - [(set (match_operand:HI 0 "general_operand" "=a") - (div:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "register_operand" "=a") + (div:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "general_operand" "rm"))) - (set (match_operand:HI 3 "general_operand" "=&d") + (set (match_operand:HI 3 "register_operand" "=&d") (mod:HI (match_dup 1) (match_dup 2)))] "" "cwtd\;idiv%W0 %2") ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodsi4" - [(set (match_operand:SI 0 "general_operand" "=a") - (udiv:SI (match_operand:SI 1 "general_operand" "0") + [(set (match_operand:SI 0 "register_operand" "=a") + (udiv:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "rm"))) - (set (match_operand:SI 3 "general_operand" "=&d") + (set (match_operand:SI 3 "register_operand" "=&d") (umod:SI (match_dup 1) (match_dup 2)))] "" "* @@ -1531,10 +1549,10 @@ ;; ??? Can we make gcc zero extend operand[0]? (define_insn "udivmodhi4" - [(set (match_operand:HI 0 "general_operand" "=a") - (udiv:HI (match_operand:HI 1 "general_operand" "0") + [(set (match_operand:HI 0 "register_operand" "=a") + (udiv:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "general_operand" "rm"))) - (set (match_operand:HI 3 "general_operand" "=&d") + (set (match_operand:HI 3 "register_operand" "=&d") (umod:HI (match_dup 1) (match_dup 2)))] "" "* @@ -1547,10 +1565,10 @@ ;;this should be a valid double division which we may want to add (define_insn "" - [(set (match_operand:SI 0 "general_operand" "=a") - (udiv:DI (match_operand:DI 1 "general_operand" "a") - (match_operand:SI 2 "general_operand" "rm"))) - (set (match_operand:SI 3 "general_operand" "=d") + [(set (match_operand:SI 0 "register_operand" "=a") + (udiv:DI (match_operand:DI 1 "register_operand" "a") + (match_operand:SI 2 "general_operand" "rm"))) + (set (match_operand:SI 3 "register_operand" "=d") (umod:SI (match_dup 1) (match_dup 2)))] "" "div%L0 %2,%0") @@ -2605,7 +2623,7 @@ ;; bt on the MEM directly. (define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "q") + [(set (cc0) (zero_extract (match_operand:QI 0 "register_operand" "q") (const_int 1) (match_operand:SI 1 "general_operand" "ri")))] "" @@ -2625,6 +2643,34 @@ RET; }") +(define_insn "" + [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") + (const_int 1) + (match_operand:SI 1 "general_operand" "ri"))) + (clobber (match_scratch:SI 2 "=&r"))] + "" + "* +{ + /* Copy memory to scratch register; pretend it was there to start with. */ + if (GET_CODE (operands[0]) == MEM) + { + output_asm_insn (AS2 (mov%L2,%0,%2), operands); + operands[0] = operands[2]; + } + if (GET_CODE (operands[1]) == CONST_INT) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, 1 << INTVAL (operands[1])); + output_asm_insn (AS2 (test%L0,%1,%0), operands); + } + else + { + operands[0] = gen_rtx (REG, SImode, REGNO (operands[0])); + cc_status.flags |= CC_Z_IN_NOT_C; + output_asm_insn (AS2 (bt%L0,%1,%0), operands); + } + RET; +}") + (define_insn "" [(set (cc0) (zero_extract (match_operand:HI 0 "nonimmediate_operand" "r") (const_int 1) @@ -2673,7 +2719,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return AS1 (setnb,%0); else return AS1 (sete,%0); @@ -2686,7 +2732,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return AS1 (setb,%0); else return AS1 (setne,%0); @@ -2753,7 +2799,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jnc %l0\"; else return \"je %l0\"; @@ -2768,7 +2814,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jc %l0\"; else return \"jne %l0\"; @@ -2915,7 +2961,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jc %l0\"; else return \"jne %l0\"; @@ -2930,7 +2976,7 @@ "" "* { - if (cc_status.flags & CC_Z_IN_NOT_C) + if (cc_prev_status.flags & CC_Z_IN_NOT_C) return \"jnc %l0\"; else return \"je %l0\"; @@ -3018,7 +3064,7 @@ "jmp %l0") (define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "a"))] + [(set (pc) (match_operand:SI 0 "general_operand" "rm"))] "" "* { @@ -3027,6 +3073,98 @@ return AS1 (jmp,%*%0); }") +;; Implement switch statements when generating PIC code. Switches are +;; implemented by `tablejump' when not using -fpic. + +;; Emit code here to do the range checking and make the index zero based. + +(define_expand "casesi" + [(parallel + [(set (pc) + (if_then_else (leu (minus:SI + (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "const_int_operand" "")) + (match_operand:SI 2 "const_int_operand" "")) + (plus:SI (mem:SI (plus:SI (pc) + (minus:SI (match_dup 0) + (match_dup 1)))) + (label_ref (match_operand 3 "" ""))) + (pc))) + (use (label_ref (match_operand 4 "" ""))) + (clobber (match_scratch:SI 5 ""))])] + "flag_pic" + " +{ + rtx reg = gen_reg_rtx (SImode); + + current_function_uses_pic_offset_table = 1; + + emit_insn (gen_subsi3 (reg, operands[0], operands[1])); + emit_insn (gen_cmpsi (reg, operands[2])); + emit_jump_insn (gen_bgtu (operands[4])); + operands[0] = reg; + operands[1] = CONST0_RTX (SImode); +}") + +;; Implement a casesi insn. + +;; Each entry in the "addr_diff_vec" looks like this as the result of the +;; two rules below: +;; +;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2] +;; +;; 1. An expression involving an external reference may only use the +;; addition operator, and only with an assembly-time constant. +;; The example above satisfies this because ".-.L2" is a constant. +;; +;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is +;; given the value of "GOT - .", where GOT is the actual address of +;; the Global Offset Table. Therefore, the .long above actually +;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The +;; expression "GOT - .L2" by itself would generate an error from as(1). +;; +;; The pattern below emits code that looks like this: +;; +;; movl %ebx,reg +;; subl TABLE@GOTOFF(%ebx,index,4),reg +;; jmp reg +;; +;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since +;; the addr_diff_vec is known to be part of this module. +;; +;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which +;; evaluates to just ".L2". + +(define_insn "" + [(set (pc) + (if_then_else (leu (minus:SI + (match_operand:SI 0 "general_operand" "r") + (match_operand:SI 1 "const_int_operand" "i")) + (match_operand:SI 2 "const_int_operand" "i")) + (plus:SI (mem:SI (plus:SI (pc) + (minus:SI (match_dup 0) + (match_dup 1)))) + (label_ref (match_operand 3 "" ""))) + (pc))) + (use (label_ref (match_operand 4 "" ""))) + (clobber (match_scratch:SI 5 "=&r"))] + "" + "* +{ + rtx xops[4]; + + xops[0] = pic_offset_table_rtx; + xops[1] = operands[5]; + xops[2] = operands[3]; + xops[3] = operands[0]; + + output_asm_insn (AS2 (mov%L1,%0,%1), xops); + output_asm_insn (\"sub%L1 %l2@GOTOFF(%0,%3,4),%1\", xops); + output_asm_insn (AS1 (jmp,%*%1), xops); + ASM_OUTPUT_ALIGN_CODE (asm_out_file); + RET; +}") + (define_insn "tablejump" [(set (pc) (match_operand:SI 0 "general_operand" "rm")) (use (label_ref (match_operand 1 "" "")))] @@ -3038,9 +3176,31 @@ return AS1 (jmp,%*%0); }") +;; Call insns. + +;; If generating PIC code, the predicate indirect_operand will fail +;; for operands[0] containing symbolic references on all of the named +;; call* patterns. Each named pattern is followed by an unnamed pattern +;; that matches any call to a symbolic CONST (ie, a symbol_ref). The +;; unnamed patterns are only used while generating PIC code, because +;; otherwise the named patterns match. + ;; Call subroutine returning no value. -(define_insn "call_pop" +(define_expand "call_pop" + [(parallel [(call (match_operand:QI 0 "indirect_operand" "") + (match_operand:SI 1 "general_operand" "")) + (set (reg:SI 7) + (plus:SI (reg:SI 7) + (match_operand:SI 3 "immediate_operand" "")))])] + "" + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") + +(define_insn "" [(call (match_operand:QI 0 "indirect_operand" "m") (match_operand:SI 1 "general_operand" "g")) (set (reg:SI 7) (plus:SI (reg:SI 7) @@ -3058,7 +3218,26 @@ return AS1 (call,%P0); }") -(define_insn "call" +(define_insn "" + [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) + (match_operand:SI 1 "general_operand" "g")) + (set (reg:SI 7) (plus:SI (reg:SI 7) + (match_operand:SI 3 "immediate_operand" "i")))] + "" + "call %P0") + +(define_expand "call" + [(call (match_operand:QI 0 "indirect_operand" "") + (match_operand:SI 1 "general_operand" ""))] + ;; Operand 1 not used on the i386. + "" + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") + +(define_insn "" [(call (match_operand:QI 0 "indirect_operand" "m") (match_operand:SI 1 "general_operand" "g"))] ;; Operand 1 not used on the i386. @@ -3075,10 +3254,31 @@ return AS1 (call,%P0); }") +(define_insn "" + [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) + (match_operand:SI 1 "general_operand" "g"))] + ;; Operand 1 not used on the i386. + "" + "call %P0") + ;; Call subroutine, returning value in operand 0 ;; (which must be a hard register). -(define_insn "call_value_pop" +(define_expand "call_value_pop" + [(parallel [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "indirect_operand" "") + (match_operand:SI 2 "general_operand" ""))) + (set (reg:SI 7) + (plus:SI (reg:SI 7) + (match_operand:SI 4 "immediate_operand" "")))])] + "" + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") + +(define_insn "" [(set (match_operand 0 "" "=rf") (call (match_operand:QI 1 "indirect_operand" "m") (match_operand:SI 2 "general_operand" "g"))) @@ -3099,7 +3299,28 @@ RET; }") -(define_insn "call_value" +(define_insn "" + [(set (match_operand 0 "" "=rf") + (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) + (match_operand:SI 2 "general_operand" "g"))) + (set (reg:SI 7) (plus:SI (reg:SI 7) + (match_operand:SI 4 "immediate_operand" "i")))] + "" + "call %P1") + +(define_expand "call_value" + [(set (match_operand 0 "" "") + (call (match_operand:QI 1 "indirect_operand" "") + (match_operand:SI 2 "general_operand" "")))] + ;; Operand 2 not used on the i386. + "" + " +{ + if (flag_pic) + current_function_uses_pic_offset_table = 1; +}") + +(define_insn "" [(set (match_operand 0 "" "=rf") (call (match_operand:QI 1 "indirect_operand" "m") (match_operand:SI 2 "general_operand" "g")))] @@ -3119,6 +3340,14 @@ RET; }") +(define_insn "" + [(set (match_operand 0 "" "=rf") + (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) + (match_operand:SI 2 "general_operand" "g")))] + ;; Operand 2 not used on the i386. + "" + "call %P1") + ;; Insn emitted into the body of a function to return from a function. ;; This is only done if the function's epilogue is known to be simple. ;; See comments for simple_386_epilogue in i386.c. -- 2.30.2