[(set_attr "type" "ibr")
(set_attr "length_immediate" "0")])
-(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
- (use (label_ref (match_operand 1 "" "")))]
- "! flag_pic"
- "jmp\t%A0"
- [(set_attr "type" "ibr")
- (set_attr "length_immediate" "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.
-;;
-;; 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_expand "casesi"
- [(set (match_dup 5)
- (match_operand:SI 0 "general_operand" ""))
- (parallel [(set (match_dup 6)
- (minus:SI (match_dup 5)
- (match_operand:SI 1 "general_operand" "")))
- (clobber (reg:CC 17))])
- (set (reg:CC 17)
- (compare:CC (match_dup 6)
- (match_operand:SI 2 "general_operand" "")))
- (set (pc)
- (if_then_else (gtu (reg:CC 17)
- (const_int 0))
- (label_ref (match_operand 4 "" ""))
- (pc)))
- (parallel
- [(set (match_dup 7)
- (minus:SI (match_dup 8)
- (mem:SI (plus:SI (plus:SI (mult:SI (match_dup 6) (const_int 4))
- (match_dup 8))
- (const (unspec [(label_ref (match_operand 3 "" ""))] 7))))))
- (clobber (reg:CC 17))])
- (parallel [(set (pc) (match_dup 7))
- (use (label_ref (match_dup 3)))])]
- "flag_pic"
+(define_expand "tablejump"
+ [(parallel [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
{
- operands[5] = gen_reg_rtx (SImode);
- operands[6] = gen_reg_rtx (SImode);
- operands[7] = gen_reg_rtx (SImode);
- operands[8] = pic_offset_table_rtx;
- current_function_uses_pic_offset_table = 1;
+ /* In PIC mode, the table entries are stored GOT-relative. Convert
+ the relative address to an absolute address. */
+ if (flag_pic)
+ {
+ operands[0] = expand_simple_binop (Pmode, MINUS, pic_offset_table_rtx,
+ operands[0], NULL_RTX, 1,
+ OPTAB_DIRECT);
+ current_function_uses_pic_offset_table = 1;
+ }
})
-(define_insn "*tablejump_pic"
+(define_insn "*tablejump_1"
[(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
(use (label_ref (match_operand 1 "" "")))]
""