📄 genarm.c
字号:
if (ap2->mode == am_immed) { ap3 = copy_addr (ap1, am_lsl); ap3->offset = ap2->offset; } else { ap3 = copy_addr (ap1, am_lslr); ap3->sreg = ap2->preg; } g_code (op_mov, cc_al, ap1, ap3, NIL_ADDRESS); return mk_legal (ap1, flags); default: FATAL ((__FILE__, "g_lshift", "typ = %d", ep->etp->type)); break; } return NIL_ADDRESS;}#if 0static ADDRESS *g_aslshift P2 (const EXPR *, ep, FLAGS, flags){ FATAL ((__FILE__, "g_aslshift", "typ = %d", ep->etp->type)); return NIL_ADDRESS;}#endifstatic ADDRESS *g_rshift P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap1, *ap2, *ap3; BOOL sign = FALSE; switch (ep->etp->type) { case bt_int32: case bt_long: sign = TRUE; /*FALLTHRU */ case bt_uint32: case bt_ulong: case bt_pointer32: ap1 = g_expr (ep->v.p[0], F_REG); ap2 = g_expr (ep->v.p[1], (FLAGS) (F_REG | F_IMMED)); validate (ap1); freeop (ap2); if (ap2->mode == am_immed) { ap3 = copy_addr (ap1, sign ? am_asr : am_lsr); ap3->offset = ap2->offset; } else { ap3 = copy_addr (ap1, sign ? am_asrr : am_lsrr); ap3->sreg = ap2->preg; } g_code (op_mov, cc_al, ap1, ap3, NIL_ADDRESS); return mk_legal (ap1, flags); default: FATAL ((__FILE__, "g_rshift", "typ = %d", ep->etp->type)); break; } return NIL_ADDRESS;}#if 0static ADDRESS *g_asrshift P2 (const EXPR *, ep, FLAGS, flags){ FATAL ((__FILE__, "g_asrshift", "typ = %d", ep->etp->type)); return NIL_ADDRESS;}#endif/* * Generate the code to extend the value in the register described by * 'ap' from type 'tp1' to the type 'tp2'. */static ADDRESS *g_extend P3 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2){ ADDRESS *ap1; AMODE mode; assert (ap->mode == am_reg); switch (tp2->type) { case bt_int16: case bt_uint16: case bt_short: case bt_ushort: case bt_int32: case bt_uint32: case bt_long: case bt_ulong: case bt_pointer32: switch (tp1->type) { case bt_char: case bt_schar: case bt_short: case bt_int16: mode = am_asr; ap1 = mk_address (am_lsl, ap->preg, (4L - tp1->size) * 8L); g_code (op_mov, cc_al, ap, ap1, NIL_ADDRESS); ap1 = mk_address (mode, ap->preg, (4L - tp1->size) * 8L); g_code (op_mov, cc_al, ap, ap1, NIL_ADDRESS); return ap; case bt_uchar: case bt_charu: case bt_ushort: case bt_uint16: mode = am_lsr; ap1 = mk_address (am_lsl, ap->preg, (4L - tp1->size) * 8L); g_code (op_mov, cc_al, ap, ap1, NIL_ADDRESS); ap1 = mk_address (mode, ap->preg, (4L - tp1->size) * 8L); g_code (op_mov, cc_al, ap, ap1, NIL_ADDRESS); return ap; case bt_int32: case bt_long: case bt_uint32: case bt_ulong: case bt_pointer32: return ap; default: break; } break; default: break; } FATAL ( (__FILE__, "g_extend", "typ1 = %d, typ2 = %d", tp1->type, tp2->type)); return NIL_ADDRESS;}static ADDRESS *g_cast P4 (ADDRESS *, ap, TYP *, tp1, TYP *, tp2, FLAGS, flags){ if (flags & F_NOVALUE) { freeop (ap); return NIL_ADDRESS; } switch (tp2->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar: ap = mk_legal (ap, (FLAGS) (F_REG | F_VOL)); ap = g_extend (ap, tp1, tp2); return mk_legal (ap, flags); case bt_short: case bt_int16: case bt_ushort: case bt_uint16: ap = mk_legal (ap, (FLAGS) (F_REG | F_VOL)); ap = g_extend (ap, tp1, tp2); return mk_legal (ap, flags); case bt_int32: case bt_long: case bt_uint32: case bt_ulong: case bt_pointer32: case bt_func: ap = mk_legal (ap, (FLAGS) (F_REG | F_VOL)); ap = g_extend (ap, tp1, tp2); return mk_legal (ap, flags); default: FATAL ( (__FILE__, "g_cast", "typ1 = %d, typ2 = %d", tp1->type, tp2->type)); break; } return NIL_ADDRESS;}/* * generate code for the assignment expression */static ADDRESS *g_assign P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap1; ADDRESS *ap2; switch (ep->v.p[0]->nodetype) { case en_register: ap1 = g_expr (ep->v.p[0], F_ALL); ap2 = g_expr (ep->v.p[1], F_REG); validate (ap1); freeop (ap2); return mk_legal (ap1, flags); case en_ref: ap1 = g_expr (ep->v.p[0], F_ALL); ap2 = g_expr (ep->v.p[1], F_REG); validate (ap1); g_code (op_str, cc_al, ap1, ap2, NIL_ADDRESS); freeop (ap2); return mk_legal (ap1, flags); default: FATAL ((__FILE__, "g_assign", "nodetype = %d", ep->v.p[0]->nodetype)); break; } return NIL_ADDRESS;}/* * generate code to evaluate a condition operator node (?:) */static ADDRESS *g_hook P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap1, *ap2; LABEL false_label, end_label; TYP *tp = ep->etp; SIZE offset; FLAGS flagx; switch (tp->type) { case bt_void: flagx = (FLAGS) (F_ALL | F_NOVALUE); break; case bt_struct: case bt_union: tp = tp_pointer; /*FALLTHROUGH */ default: flagx = (FLAGS) (F_REG | F_VOL); } false_label = nextlabel++; end_label = nextlabel++; temp_inv (); /* I do not think I can avoid that */ offset = stack_offset; stack_offset = 0L; /* all registers are void */ g_falsejp (ep->v.p[0], false_label); ep = ep->v.p[1]; /* all registers are void */ ap1 = g_expr (ep->v.p[0], flagx); freeop (ap1); /* all registers are void */ g_branch (end_label); g_label (false_label); ap2 = g_expr (ep->v.p[1], flagx); g_label (end_label); g_stack (stack_offset); stack_offset = offset; return mk_legal (ap2, flags);}/*--------------------------------------------------------------------------*/static SIZE push_param P1 (const EXPR *, ep){ (void) ep; return 0L;}/* * generate the function return addressing mode */static ADDRESS *func_result P3 (FLAGS, flags, SIZE, size, const EXPR *, ep){ ADDRESS *ap; (void) size; (void) ep; if (flags & F_NOVALUE) { return NIL_ADDRESS; } ap = data_register (); return ap;}/* * generate the parameters for a function call */static SIZE g_parms P1 (const EXPR *, ep){ SIZE size; for (size = 0L; ep != NIL_EXPR; ep = ep->v.p[1]) { size += push_param (ep->v.p[0]); } return size;}/* * generate a function call node and return the addressing mode of the result */static ADDRESS *g_fcall P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap; SIZE size; EXPR *ep0 = ep->v.p[0]; if (!is_parameter) { switch (stackopt_option) { case 1: /* * "Safe" stack optimisation. Perform a stack optimisation * unless: * 1. The alloca() routine is called * 2. The function call is via a variable * 3. The function starts with an underscore character */ if ((ep0->nodetype != en_nacon) || (ep0->v.str[0] == (CHAR) '_') || (ep0->v.str == alloca_name)) { g_stack (stack_offset); } break; case 2: /* * "Forced" stack optimisation. This will not suppress * the optimisation on encountering calls to functions * whose names begin with underscore. */ if ((ep0->nodetype != en_nacon) || (ep0->v.str == alloca_name)) { g_stack (stack_offset); } break; default: case 0: /* * no stack optimisation */ g_stack (stack_offset); break; } } temp_inv (); /* push any used temporary registers */ size = g_parms (ep0); /* generate parameters */ switch (ep0->nodetype) { case en_nacon: case en_labcon: ap = mk_direct (ep0); g_code (op_bl, cc_al, ap, NIL_ADDRESS, NIL_ADDRESS); break; default: ap = g_expr (ep0, F_REG); g_code (op_mov, cc_al, mk_reg (R15), ap, NIL_ADDRESS); break; } return func_result (flags, size, ep);}#ifdef ASMstatic ADDRESS *g_asm P1 (const EXPR *, ep){ ADDRESS *ap = mk_amode (am_str); ap->offset = copynode (ep); g_code (op_asm, cc_al, ap, NIL_ADDRESS, NIL_ADDRESS); return NIL_ADDRESS;}#endif /* ASM *//*--------------------------------------------------------------------------*//* * general expression evaluation. returns the addressing mode of the result */static ADDRESS *g_expr P2 (const EXPR *, ep, FLAGS, flags){ ADDRESS *ap1; LABEL lab0, lab1; CONDITION cc; static CONDITION reverse_cc[] = { cc_nv, /* cc_al */ cc_cs, /* cc_cc */ cc_cc, /* cc_cs */ cc_ne, /* cc_eq */ cc_lt, /* cc_ge */ cc_le, /* cc_gt */ cc_ls, /* cc_hi */ cc_gt, /* cc_le */ cc_hi, /* cc_ls */ cc_ge, /* cc_lt */ cc_pl, /* cc_mi */ cc_eq, /* cc_ne */ cc_al, /* cc_nv */ cc_mi, /* cc_pl */ cc_vs, /* cc_vc */ cc_vc /* cc_vs */ }; if (tst_const (ep)) { ap1 = mk_amode (am_immed); ap1->offset = copynode (ep); return mk_legal (ap1, flags); } switch (ep->nodetype) { case en_register: ap1 = mk_reg (ep->v.r); return mk_legal (ap1, flags); case en_ref: ap1 = g_deref (ep->v.p[0], flags); return mk_legal (ap1, flags); case en_uminus: return g_uminus (ep, flags); case en_compl: return g_negate (ep, flags); case en_add: return g_add (ep, flags, op_add); case en_sub: return g_add (ep, flags, op_sub); case en_mul: return g_mul (ep, flags); case en_div: return g_div (ep, flags); case en_mod: return g_mod (ep, flags); case en_and: return g_logic (ep, flags, op_and); case en_or: return g_logic (ep, flags, op_orr); case en_xor: return g_logic (ep, flags, op_eor); case en_lsh: return g_lshift (ep, flags); case en_rsh: return g_rshift (ep, flags); case en_asadd: return g_asadd (ep, flags, op_add); case en_assub: return g_asadd (ep, flags, op_sub); case en_asmul: return g_asmul (ep, flags); case en_asdiv: return g_asdiv (ep, flags); case en_asmod: return g_asmod (ep, flags); case en_asand: return g_aslogic (ep, flags, op_and); case en_asor: return g_aslogic (ep, flags, op_orr); case en_asxor: return g_aslogic (ep, flags, op_eor); case en_aslsh: return g_lshift (ep, flags); case en_asrsh: return g_rshift (ep, flags); case en_assign: return g_assign (ep, flags); case en_comma: freeop (g_expr (ep->v.p[0], (FLAGS) (F_ALL | F_NOVALUE))); return g_expr (ep->v.p[1], flags); case en_cast: return g_cast (g_expr (ep->v.p[0], F_ALL), ep->v.p[0]->etp, ep->etp, flags); case en_eq: cc = cc_eq; VOIDCAST g_compare (ep); goto cont1; case en_ne: cc = cc_eq; VOIDCAST g_compare (ep); goto cont1; case en_lt: cc = g_compare (ep) ? cc_cc : cc_lt; goto cont1; case en_le: cc = g_compare (ep) ? cc_ls : cc_le; goto cont1; case en_gt: cc = g_compare (ep) ? cc_hi : cc_gt; goto cont1; case en_ge: cc = g_compare (ep) ? cc_cs : cc_ge; cont1: ap1 = data_register (); g_code (op_mov, cc, ap1, mk_immed (1L), NIL_ADDRESS); g_code (op_mov, reverse_cc[cc], ap1, mk_immed (0L), NIL_ADDRESS); return mk_legal (ap1, flags); case en_land: case en_lor: case en_not: lab0 = nextlabel++; lab1 = nextlabel++; g_falsejp (ep, lab0); ap1 = data_register (); g_code (op_mov, cc_al, ap1, mk_immed (1L), NIL_ADDRESS); g_branch (lab1); g_code (op_mov, cc_al, ap1, mk_immed (0L), NIL_ADDRESS); g_label (lab1); return mk_legal (ap1, flags); case en_cond: return g_hook (ep, flags); case en_fcall: case en_call:
case en_usercall: return g_fcall (ep, flags);#ifdef ASM case en_str: return g_asm (ep);#endif /* ASM */ default: FATAL ((__FILE__, "g_expr", "uncoded ep %d", ep->nodetype)); break; } return NIL_ADDRESS;}PRIVATE void g_expression P1 (const EXPR *, ep){ initstack (); if (ep != NIL_EXPR) { VOIDCAST g_expr (ep, (FLAGS) (F_ALL | F_NOVALUE)); } checkstack ();}/* * generate code to do a comparison of the two operands of node. returns 1 if * it was an unsigned comparison */static BOOL g_compare P1 (const EXPR *, ep){ ADDRESS *ap1, *ap2; BOOL sign = FALSE; switch (ep->v.p[0]->etp->type) { case bt_char: case bt_schar: case bt_short: case bt_int16: case bt_int32: case bt_long: sign = TRUE; /*FALLTHRU */ case bt_uchar: case bt_charu: case bt_ushort: case bt_uint16: case bt_uint32: case bt_ulong: case bt_pointer32: ap2 = g_expr (ep->v.p[1], F_ALL); ap1 = g_expr (ep->v.p[0], F_REG); validate (ap2); g_code (op_cmps, cc_al, ap1, ap2, NIL_ADDRESS); freeop (ap1); freeop (ap2); return sign; default: FATAL ((__FILE__, "g_compare", "typ = %d", ep->etp->type)); break; } return FALSE;}/* * Test the expression and set the condition codes accordingly
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -