void release(void) { if (!rsodepth) return; rsodepth--; while (rsdepth > rsold[rsodepth]) { int data = regstack[--rsdepth]; if (data <8) { gen_pop(data,am_dreg,0); dregs[data] = 1; } else if (data < 16) { gen_pop(data & 7,am_areg,0); aregs[data-8] = 1; } else { gen_pop(data & 7,am_freg,0); fregs[data-16] = 1; } } max_addr = next_addr < cf_freeaddress ? cf_freeaddress-1 : next_addr-1; max_data = next_data < cf_freedata ? cf_freedata-1 : next_data-1; max_float = next_float < cf_freefloat ? cf_freefloat-1 : next_float-1; }
/** * add the primary and secondary registers * if lval2 is int pointer and lval is not, scale lval * @param lval * @param lval2 */ void gen_add(LVALUE *lval, LVALUE *lval2) { gen_pop (); if (dbltest (lval2, lval)) { gen_swap (); gen_multiply_by_two (); gen_swap (); } output_line ("dad \td"); }
/** * store the specified object type in the primary register * at the address in secondary register (on the top of the stack) * @param typeobj */ void gen_put_indirect(char typeobj) { gen_pop (); if (typeobj & CCHAR) { //gen_call("ccpchar"); output_line("mov \ta,l"); output_line("stax\td"); } else { if (uflag) { output_line("shlx"); } else { gen_call("ccpint"); } } }
void Compiler::handle_ik_stack(const JInst& jinst) { switch(jinst.opcode) { case OPCODE_POP: gen_pop(m_jframe->top()); break; case OPCODE_POP2: gen_pop2(); break; case OPCODE_DUP: case OPCODE_DUP_X1: case OPCODE_DUP_X2: case OPCODE_DUP2: case OPCODE_DUP2_X1: case OPCODE_DUP2_X2: case OPCODE_SWAP: gen_dup(jinst.opcode); break; default: assert(false); break; } }
/** * arithmetic shift left the secondary register the number of * times in the primary register (results in primary register) */ void gen_arithm_shift_left(void) { gen_pop (); gen_call ("ccasl"); }
/** * logically shift right the secondary register the number of * times in the primary register (results in primary register) */ void gen_logical_shift_right(void) { gen_pop(); gen_call ("cclsr"); }
void genreturn(SNODE *stmt, int flag) /* * generate a return statement. */ { AMODE *ap,*ap1; int size; if( stmt != 0 && stmt->exp != 0 ) { initstack(); if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) { size = currentfunc->tp->btp->size; ap = gen_expr(stmt->exp,F_ALL,4); if (!(save_mask & 0x40)) gen_push(ESI,am_dreg,0); if (!(save_mask & 0x80)) gen_push(EDI,am_dreg,0); if (prm_linkreg) { ap1 = xalloc(sizeof(AMODE)); ap1->preg = EBP; ap1->mode = am_indisp; if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) ap1->offset = makenode(en_icon,(char *)(currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size+3) &0xFFFFFFFCL)),0); else ap1->offset = makenode(en_icon,(char *)8,0); } else if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) ap1 = make_stack(-stackdepth-framedepth-currentfunc->tp->lst.head->value.i-((currentfunc->tp->lst.head->tp->size+3) & 0xfffffffcL)); else ap1 = make_stack(-stackdepth-framedepth); gen_code(op_mov,4,makedreg(ESI),ap); gen_code(op_mov,4,makedreg(EDI),ap1); gen_code(op_mov,4,makedreg(EAX),makedreg(EDI)); gen_code(op_mov,4,makedreg(ECX),make_immed(size)); gen_code(op_cld,0,0,0); gen_code(op_rep,1,0,0); gen_code(op_movsb,1,0,0); if (!(save_mask & 0x80)) gen_pop(EDI,am_dreg,0); if (!(save_mask & 0x40)) gen_pop(ESI,am_dreg,0); } else { size = currentfunc->tp->btp->size; ap = gen_expr(stmt->exp,F_DREG | F_FREG,size); if (size > 4) { if (ap->mode != am_freg) gen_code(op_fld,size,ap,0); } else if( ap->mode != am_dreg || ap->preg != 0 ) gen_code(op_mov,size,makedreg(0),ap); } freeop(ap); } if (flag) { if( retlab != -1 ) gen_label(retlab); if( fsave_mask != 0 ) diag("Float restore in return"); if (!prm_linkreg && lc_maxauto) gen_code(op_add,4,makedreg(ESP),make_immed(lc_maxauto)); if (currentfunc->intflag) { gen_code(op_popad,0,0,0); if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) { gen_code(op_leave,0,0,0); } gen_code(op_iretd,0,0,0); } else { if( save_mask != 0 ) popregs(save_mask); if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) { gen_code(op_leave,0,0,0); } if (currentfunc->pascaldefn) { long retsize = 0; if (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) { retsize = currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size + 3) & 0xfffffffcL); if (prm_linkreg) retsize -= 8; } if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) retsize += 4; if (retsize) { gen_code(op_ret,0,make_immed(retsize),0); return; } } gen_code(op_ret,0,0,0); } } else { if (retlab == -1) retlab = nextlabel++; gen_code(op_jmp,0,make_label(retlab),0); } }
/** * greater than (unsigned) */ void gen_usigned_greater_than(void) { gen_pop(); gen_call ("ccugt"); }
/** * less than (unsigned) */ void gen_unsigned_less_than(void) { gen_pop(); gen_call ("ccult"); }
/** * greater than (signed) */ void gen_greater_than(void) { gen_pop(); gen_call ("ccgt"); }
/** * less than (signed) */ void gen_less_than(void) { gen_pop(); gen_call ("cclt"); }
/** * divide the secondary register by the primary * (quotient in primary, remainder in secondary) */ void gen_div(void) { gen_pop(); gen_call ("ccdiv"); }
/** * multiply the primary and secondary registers (result in primary) */ void gen_mult(void) { gen_pop(); gen_call ("ccmul"); }
/** * subtract the primary register from the secondary */ void gen_sub(void) { gen_pop (); gen_call ("ccsub"); }
/** * equal */ void gen_equal(void) { gen_pop(); gen_call ("cceq"); }
/** * not equal */ void gen_not_equal(void) { gen_pop(); gen_call ("ccne"); }
/** * unsigned divide the secondary register by the primary * (quotient in primary, remainder in secondary) */ void gen_udiv(void) { gen_pop(); gen_call ("ccudiv"); }
/** * less than or equal (signed) */ void gen_less_or_equal(void) { gen_pop(); gen_call ("ccle"); }
/** * inclusive 'or' the primary and secondary registers */ void gen_or(void) { gen_pop(); gen_call ("ccor"); }
/** * greater than or equal (signed) */ void gen_greater_or_equal(void) { gen_pop(); gen_call ("ccge"); }
/** * exclusive 'or' the primary and secondary registers */ void gen_xor(void) { gen_pop(); gen_call ("ccxor"); }
/** * less than or equal (unsigned) */ void gen_unsigned_less_or_equal(void) { gen_pop(); gen_call ("ccule"); }
/** * 'and' the primary and secondary registers */ void gen_and(void) { gen_pop(); gen_call ("ccand"); }
/** * greater than or equal (unsigned) */ void gen_unsigned_greater_or_equal(void) { gen_pop(); gen_call ("ccuge"); }
/** * arithmetic shift right the secondary register the number of * times in the primary register (results in primary register) */ void gen_arithm_shift_right(void) { gen_pop(); gen_call ("ccasr"); }