📄 gmicro.c
字号:
/* If one operand is decrementing and one is incrementing decrement the former register explicitly and change that operand into ordinary indexing. */ if (optype0 == PUSHOP && optype1 == POPOP) { operands[0] = XEXP (XEXP (operands[0], 0), 0); output_asm_insn ("sub.w %#8,%0", operands); operands[0] = gen_rtx (MEM, DImode, operands[0]); optype0 = OFFSOP; } if (optype0 == POPOP && optype1 == PUSHOP) { operands[1] = XEXP (XEXP (operands[1], 0), 0); output_asm_insn ("sub.w %#8,%1", operands); operands[1] = gen_rtx (MEM, DImode, operands[1]); optype1 = OFFSOP; } /* If an operand is an unoffsettable memory ref, find a register we can increment temporarily to make it refer to the second word. */ if (optype0 == MEMOP) addreg0 = find_addr_reg (operands[0]); if (optype1 == MEMOP) addreg1 = find_addr_reg (operands[1]); /* Ok, we can do one word at a time. Normally we do the low-numbered word first, but if either operand is autodecrementing then we do the high-numbered word first. In either case, set up in LATEHALF the operands to use for the high-numbered word and in some cases alter the operands in OPERANDS to be suitable for the low-numbered word. */ if (optype0 == REGOP) latehalf[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); else if (optype0 == OFFSOP) latehalf[0] = adj_offsettable_operand (operands[0], 4); else latehalf[0] = operands[0]; if (optype1 == REGOP) latehalf[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); else if (optype1 == OFFSOP) latehalf[1] = adj_offsettable_operand (operands[1], 4); else if (optype1 == CNSTOP) { if (GET_CODE (operands[1]) == CONST_DOUBLE) split_double (operands[1], &operands[1], &latehalf[1]); else if (CONSTANT_P (operands[1])) latehalf[1] = const0_rtx; } else latehalf[1] = operands[1]; /* If insn is effectively movd N(sp),-(sp) then we will do the high word first. We should use the adjusted operand 1 (which is N+4(sp)) for the low word as well, to compensate for the first decrement of sp. */ if (optype0 == PUSHOP && REGNO (XEXP (XEXP (operands[0], 0), 0)) == STACK_POINTER_REGNUM && reg_overlap_mentioned_p (stack_pointer_rtx, operands[1])) operands[1] = latehalf[1]; /* If one or both operands autodecrementing, do the two words, high-numbered first. */ /* Likewise, the first move would clobber the source of the second one, do them in the other order. This happens only for registers; such overlap can't happen in memory unless the user explicitly sets it up, and that is an undefined circumstance. */ if (optype0 == PUSHOP || optype1 == PUSHOP || (optype0 == REGOP && optype1 == REGOP && REGNO (operands[0]) == REGNO (latehalf[1]))) { /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) output_asm_insn ("add.w %#4,%0", &addreg0); if (addreg1) output_asm_insn ("add.w %#4,%0", &addreg1); /* Do that word. */ output_asm_insn (singlemove_string (latehalf), latehalf); /* Undo the adds we just did. */ if (addreg0) output_asm_insn ("sub.w %#4,%0", &addreg0); if (addreg1) output_asm_insn ("sub.w %#4,%0", &addreg1); /* Do low-numbered word. */ return singlemove_string (operands); } /* Normal case: do the two words, low-numbered first. */ output_asm_insn (singlemove_string (operands), operands); /* Make any unoffsettable addresses point at high-numbered word. */ if (addreg0) output_asm_insn ("add.w %#4,%0", &addreg0); if (addreg1) output_asm_insn ("add.w %#4,%0", &addreg1); /* Do that word. */ output_asm_insn (singlemove_string (latehalf), latehalf); /* Undo the adds we just did. */ if (addreg0) output_asm_insn ("sub.w %#4,%0", &addreg0); if (addreg1) output_asm_insn ("sub.w %#4,%0", &addreg1); return "";}/* Move const_double to floating point register (DF) */char *output_move_const_double (operands) rtx *operands;{ int code = standard_fpu_constant_p (operands[1]); if (FPU_REG_P (operands[0])) { if (code != 0) { static char buf[40]; sprintf (buf, "fmvr from%d,%%0.d", code); return buf; } else { return "fmov %1,%0.d"; } } else if (GREG_P (operands[0])) { rtx xoperands[2]; xoperands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); xoperands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_HIGH (operands[1])); output_asm_insn ("mov.w %1,%0", xoperands); operands[1] = gen_rtx (CONST_INT, VOIDmode, CONST_DOUBLE_LOW (operands[1])); return "mov.w %1,%0"; } else { return output_move_double (operands); /* ?????? */ }}char *output_move_const_single (operands) rtx *operands;{ int code = standard_fpu_constant_p (operands[1]); static char buf[40]; if (FPU_REG_P (operands[0])) { if (code != 0) { sprintf (buf, "fmvr from%d,%%0.s", code); return buf; } return "fmov.s %f1,%0"; } else return "mov.w %f1,%0";}/* Return nonzero if X, a CONST_DOUBLE, has a value that we can get from the "fmvr" instruction of the Gmicro FPU. The value, anded with 0xff, gives the code to use in fmovecr to get the desired constant. */ u.i[0] = CONST_DOUBLE_LOW (x); u.i[1] = CONST_DOUBLE_HIGH (x); d = u.d; if (d == 0.0) /* +0.0 */ return 0x0; /* Note: there are various other constants available but it is a nuisance to put in their values here. */ if (d == 1.0) /* +1.0 */ return 0x1; /* * Stuff that looks different if it's single or double */ if (GET_MODE (x) == SFmode) { if (d == S_PI) return 0x2; if (d == (S_PI / 2.0)) return 0x3; if (d == S_E) return 0x4; if (d == S_LOGEof2) return 0x5; if (d == S_LOGEof10) return 0x6; if (d == S_LOG10of2) return 0x7; if (d == S_LOG10ofE) return 0x8; if (d == S_LOG2ofE) return 0x9; } else { if (d == D_PI) return 0x2; if (d == (D_PI / 2.0)) return 0x3; if (d == D_E) return 0x4; if (d == D_LOGEof2) return 0x5; if (d == D_LOGEof10) return 0x6; if (d == D_LOG10of2) return 0x7; if (d == D_LOG10ofE) return 0x8; if (d == D_LOG2ofE) return 0x9; } return 0;}#undef S_PI#undef D_PI#undef S_E#undef D_E#undef S_LOGEof2#undef D_LOGEof2#undef S_LOGEof10#undef D_LOGEof10#undef S_LOG10of2#undef D_LOG10of2#undef S_LOG10ofE#undef D_LOG10ofE#undef S_LOG2ofE#undef D_LOG2ofE/* dest should be operand 0 *//* imm should be operand 1 */extern char *sub_imm_word ();char *add_imm_word (imm, dest, immp) int imm; rtx dest, *immp;{ int is_reg, short_ok; if (imm < 0) { *immp = gen_rtx (CONST_INT, VOIDmode, -imm); return sub_imm_word (-imm, dest); } if (imm == 0) return "mov:l.w #0,%0"; short_ok = short_format_ok (dest); if (short_ok && imm <= 8) return "add:q %1,%0.w"; if (imm < 128) return "add:e %1,%0.w"; is_reg = (GET_CODE (dest) == REG); if (is_reg) return "add:l %1,%0.w"; if (short_ok) return "add:i %1,%0.w"; return "add %1,%0.w";}char *sub_imm_word (imm, dest, immp) int imm; rtx dest, *immp;{ int is_reg, short_ok; if (imm < 0 && imm != 0x80000000) { *immp = gen_rtx (CONST_INT, VOIDmode, -imm); return add_imm_word (-imm, dest); } if (imm == 0) return "mov:z.w #0,%0"; short_ok = short_format_ok (dest); if (short_ok && imm <= 8) return "sub:q %1,%0.w"; if (imm < 128) return "sub:e %1,%0.w"; is_reg = (GET_CODE (dest) == REG); if (is_reg) return "sub:l %1,%0.w"; if (short_ok) return "sub:i %1,%0.w"; return "sub %1,%0.w";}intshort_format_ok (x) rtx x;{ rtx x0, x1; if (GET_CODE (x) == REG) return 1; if (GET_CODE (x) == MEM && GET_CODE (XEXP (x, 0)) == PLUS) { x0 = XEXP (XEXP (x, 0), 0); x1 = XEXP (XEXP (x, 0), 1); return ((GET_CODE (x0) == REG && CONSTANT_P (x1) && ((unsigned) (INTVAL (x1) + 0x8000) < 0x10000)) || (GET_CODE (x1) == REG && CONSTANT_P (x0) && ((unsigned) (INTVAL (x0) + 0x8000) < 0x10000))); } return 0;}myoutput_sp_adjust (file, op, fsize) FILE *file; char *op; int fsize;{ if (fsize == 0) ; else if (fsize < 8) fprintf (file, "\t%s:q #%d,sp.w\n", op, fsize); else if (fsize < 128) fprintf (file, "\t%s:e #%d,sp.w\n", op, fsize); else fprintf (file, "\t%s:l #%d,sp.w\n", op, fsize);}char *mov_imm_word (imm, dest) int imm; rtx dest;{ int is_reg, short_ok; if (imm == 0) return "mov:z.w #0,%0"; short_ok = short_format_ok (dest); if (short_ok && imm > 0 && imm <= 8) return "mov:q %1,%0.w"; if (-128 <= imm && imm < 128) return "mov:e %1,%0.w"; is_reg = (GET_CODE (dest) == REG); if (is_reg) return "mov:l %1,%0.w"; if (short_ok) return "mov:i %1,%0.w"; return "mov %1,%0.w";}char *cmp_imm_word (imm, dest) int imm; rtx dest;{ int is_reg, short_ok; if (imm == 0) return "cmp:z.w #0,%0"; short_ok = short_format_ok (dest); if (short_ok && imm >0 && imm <= 8) return "cmp:q %1,%0.w"; if (-128 <= imm && imm < 128) return "cmp:e %1,%0.w"; is_reg = (GET_CODE (dest) == REG); if (is_reg) return "cmp:l %1,%0.w"; if (short_ok) return "cmp:i %1,%0.w"; return "cmp %1,%0.w";}char *push_imm_word (imm) int imm;{ if (imm == 0) return "mov:z.w #0,%-"; if (imm > 0 && imm <= 8) return "mov:q %1,%-.w"; if (-128 <= imm && imm < 128) return "mov:e %1,%-.w"; return "mov:g %1,%-.w"; /* In some cases, g-format may be better than I format.?? return "mov %1,%0.w"; */}my_signed_comp (insn) rtx insn;{ rtx my_insn; my_insn = NEXT_INSN (insn); if (GET_CODE (my_insn) != JUMP_INSN) { fprintf (stderr, "my_signed_comp: Not Jump_insn "); myabort (GET_CODE (my_insn)); } my_insn = PATTERN (my_insn); if (GET_CODE (my_insn) != SET) { fprintf (stderr, "my_signed_comp: Not Set "); myabort (GET_CODE (my_insn)); } my_insn = SET_SRC (my_insn); if (GET_CODE (my_insn) != IF_THEN_ELSE) { fprintf (stderr, "my_signed_comp: Not if_then_else "); myabort (GET_CODE (my_insn)); } switch (GET_CODE (XEXP (my_insn, 0))) { case NE: case EQ: case GE: case GT: case LE: case LT: return 1; case GEU: case GTU: case LEU: case LTU: return 0; } fprintf (stderr, "my_signed_comp: Not cccc "); myabort (GET_CODE (XEXP (my_insn, 0)));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -