📄 arm.md
字号:
(sqrt:DF (match_operand:DF 1 "register_operand" "f")))] "" "* return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));")(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "register_operand" "=r") (not:SI (match_operand:SI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands));");; Fixed <--> Floating conversion insns(define_insn "floatsisf2" [(set (match_operand:SF 0 "register_operand" "=f") (float:SF (match_operand:SI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"flts\\t%0, %1\", operands));")(define_insn "floatsidf2" [(set (match_operand:DF 0 "register_operand" "=f") (float:DF (match_operand:SI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));");; Truncation insns(define_insn "truncdfsf2" [(set (match_operand:SF 0 "register_operand" "=f") (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] "" "* return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));");; Zero extension instructions.(define_expand "zero_extendhisi2" [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "register_operand" "") (const_int 16))) (set (match_operand:SI 0 "register_operand" "") (lshiftrt:SI (match_dup 2) (const_int 16)))] "" "{ operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }")(define_insn "zero_extendqihi2" [(set (match_operand:HI 0 "register_operand" "=r") (zero_extend:HI (match_operand:QI 1 "register_operand" "r")))] "" "* return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands));")(define_insn "zero_extendqisi2" [(set (match_operand:SI 0 "register_operand" "=r,r") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands)); case 1: return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands)); }")(define_expand "extendhisi2" [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "register_operand" "") (const_int 16))) (set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_dup 2) (const_int 16)))] "" "{ operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }")(define_expand "extendqihi2" [(set (match_dup 2) (ashift:SI (match_operand:QI 1 "register_operand" "") (const_int 24))) (set (match_operand:HI 0 "register_operand" "") (ashiftrt:SI (match_dup 2) (const_int 24)))] "" "{ operands[0] = gen_lowpart (SImode, operands[0]); operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }")(define_expand "extendqisi2" [(set (match_dup 2) (ashift:SI (match_operand:QI 1 "register_operand" "") (const_int 24))) (set (match_operand:SI 0 "register_operand" "") (ashiftrt:SI (match_dup 2) (const_int 24)))] "" "{ operands[1] = gen_lowpart (SImode, operands[1]); operands[2] = gen_reg_rtx (SImode); }")(define_insn "extendsfdf2" [(set (match_operand:DF 0 "register_operand" "=f") (float_extend:DF (match_operand:SF 1 "register_operand" "f")))] "" "* return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));");; Move insns (including loads and stores);; XXX Just some ideas about movti.;;(define_expand "loadti";; [(set (match_operand:TI 0 "register_operand" "");; (mem:TI (match_operand:SI 1 "address_operand" "")))];; "" "");;(define_expand "storeti";; [(set (mem:TI (match_operand:TI 0 "address_operand" ""));; (match_operand:TI 1 "register_operand" ""))];; "" "");;(define_expand "movti";; [(set (match_operand:TI 0 "general_operand" "");; (match_operand:TI 1 "general_operand" ""))];; "";; ";;{;; rtx insn;;;;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM);; operands[1] = copy_to_reg (operands[1]);;; if (GET_CODE (operands[0]) == MEM);; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);;; else if (GET_CODE (operands[1]) == MEM);; insn = gen_loadti (operands[0], XEXP (operands[1], 0));;; else;; FAIL;;;;; emit_insn (insn);;; DONE;;;}");; Recognise garbage generated above.;;(define_insn "";; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m");; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))];; "";; "*;; {;; register mem = (which_alternative < 3);;; register char *template;;;;; operands[mem] = XEXP (operands[mem], 0);;; switch (which_alternative);; {;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;;; case 1: template = \"ldmia\\t%1!, %M0\"; break;;; case 2: template = \"ldmia\\t%1, %M0\"; break;;; case 3: template = \"stmdb\\t%0!, %M1\"; break;;; case 4: template = \"stmia\\t%0!, %M1\"; break;;; case 5: template = \"stmia\\t%0, %M1\"; break;;; };; return (arm_output_asm_insn (template, operands));;; }")(define_insn "movdi" [(set (match_operand:DI 0 "di_operand" "=r,r,r,o,r") (match_operand:DI 1 "di_operand" "r,n,o,r,F"))] "" "* return (output_move_double (operands));")(define_insn "movsi" [(set (match_operand:SI 0 "general_operand" "=r,r,r,m") (match_operand:SI 1 "general_operand" "r,n,m,r"))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); case 1: return (output_mov_immediate (operands)); case 2: if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0))) return (arm_output_llc (operands)); else return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands)); case 3: return (arm_output_asm_insn (\"str\\t%1, %0\", operands)); }");; XXX The movhi stuff isn't as correct or as nice as it could be...;; Subroutine to load a half word into a register from memory.;; Operand 0 is the destination register (HImode).;; Operand 1 is the source address (SImode).;; Operand 2 is a temporary (SImode).;;(define_expand "loadhi";; [;; load the whole word (ARM realigns it if not on word boundary);; (set (match_operand:SI 2 "register_operand" "");; (mem:SI (match_operand:SI 1 "address_operand" "")));; ;; quietly forget the upper 16 bits;; (set (match_operand:HI 0 "register_operand" "");; (subreg:HI (match_dup 2) 0))];; "";; "";;);; Load op0 from mem:op1. Subroutine in case we're reloading and the normal;; loadhi is not allowed.;;(define_expand "reloadhi";; [(set (reg:SI 10);; (mem:SI (match_operand:SI 1 "address_operand" "")));; (set (match_operand:HI 0 "register_operand" "");; (subreg:HI (reg:SI 10) 0))];; "" "");; Store op0 into mem:op1. Subroutine in case we're reloading and the normal;; storehi is not allowed.(define_expand "restorehi" [(set (mem:QI (match_operand 1 "" "")) (match_dup 2)) (set (reg:SI 10) (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) (set (mem:QI (plus:SI (match_dup 1) (const_int 1))) (reg:QI 10))] "" "{ operands[2] = gen_lowpart (QImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]);}");; Subroutine to store a half word from a register into memory.;; Operand 0 is the source register (HImode);; Operand 1 is the destination address in a register (SImode)(define_expand "storehi" [;; store the low byte (set (mem:QI (match_operand 1 "" "")) (match_dup 3)) ;; extract the high byte (set (match_dup 2) (ashiftrt:SI (match_operand 0 "" "") (const_int 8))) ;; store the high byte (set (mem:QI (plus (match_dup 1) (const_int 1))) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe "" "{ operands[3] = gen_lowpart (QImode, operands[0]); operands[0] = gen_lowpart (SImode, operands[0]); operands[2] = gen_reg_rtx (SImode); }");; Subroutine to store a half word integer constant into memory.;; Operand 0 is the constant;; Operand 1 is the destination address in a register (SImode)(define_expand "storeinthi" [;; store the low byte (set (mem:QI (match_operand 1 "" "")) (match_operand 0 "" "")) ;; store the high byte (set (mem:QI (plus (match_dup 1) (const_int 1))) (match_dup 2))] "" " { int value = INTVAL (operands[0]); operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255)); operands[2] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255)); }")(define_expand "movhi" [(set (match_operand:HI 0 "general_operand" "") (match_operand:HI 1 "general_operand" ""))] "" "{ rtx insn; if (reload_in_progress || reload_completed) { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == REG) insn = gen_restorehi (operands[1], XEXP (operands[0], 0)); else insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]); } else { if (GET_CODE (operands[0]) == MEM) { if (GET_CODE (operands[1]) == CONST_INT) { insn = gen_storeinthi (operands[1], force_reg (SImode, XEXP (operands[0], 0))); } else { if (GET_CODE (operands[1]) == MEM) operands[1] = copy_to_reg (operands[1]); insn = gen_storehi (operands[1], force_reg (SImode, XEXP (operands[0], 0))); } }#if 0 else if (GET_CODE (operands[1]) == MEM) { insn = gen_loadhi (operands[0], XEXP (operands[1], 0), gen_reg_rtx (SImode)); }#endif else insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]); } emit_insn (insn); DONE;}");; Pattern to recognise insn generated default case above(define_insn "" [(set (match_operand:HI 0 "general_operand" "=r,r,r,m") (match_operand:HI 1 "general_operand" "r,n,m,r"))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"mov\\t%0, %1\\t@movhi\", operands)); case 1: return (output_mov_immediate (operands)); case 2: return (arm_output_asm_insn (\"ldr\\t%0, %1\\t@movhi\", operands)); case 3: return (arm_output_asm_insn (\"str\\t%1, %0\\t@movhi\", operands)); }")(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=r,r,r,m") (match_operand:QI 1 "general_operand" "r,n,m,r"))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); case 1: return (output_mov_immediate (operands)); case 2: return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands)); case 3: return (arm_output_asm_insn (\"strb\\t%1, %0\", operands)); }")(define_insn "movsf" [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r") (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands)); case 1: return (arm_output_asm_insn (\"ldfs\\t%0, %1\", operands)); case 2: return (arm_output_asm_insn (\"stfs\\t%1, %0\", operands)); case 3: arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands); return (arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands)); case 4: arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands); return (arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands)); case 5: return (arm_output_asm_insn (\"mov\\t%0, %1\", operands)); }")(define_insn "movdf" [(set (match_operand:DF 0 "general_operand" "=f,f,m,f,r,r") (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))] "" "* switch (which_alternative) { case 0: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands)); case 1: return (arm_output_asm_insn (\"ldfd\\t%0, %1\", operands)); case 2: return (arm_output_asm_insn (\"stfd\\t%1, %0\", operands)); case 3: return (output_mov_double_fpu_from_arm (operands)); case 4: return (output_mov_double_arm_from_fpu (operands)); case 5: return (output_move_double (operands)); }");; Comparison and test insns(define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r") (match_operand:SI 1 "arm_rhs_operand" "rI")))] "" "* return (arm_output_asm_insn (\"cmp\\t%0, %1\", operands));")(define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "register_operand" "r"))] "" "* return (arm_output_asm_insn (\"cmp\\t%0, #0\", operands));")(define_insn "" [(set (cc0) (compare (match_operand:SI 0 "register_operand" "r")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -