/** * perform a function call * called from "hier11", this routine will either call the named * function, or if the supplied ptr is zero, will call the contents * of HL * @param ptr name of the function */ void callfunction(char *ptr) { int nargs; nargs = 0; blanks (); if (ptr == 0) gen_push (HL_REG); while (!streq (line + lptr, ")")) { if (endst ()) break; expression (NO); if (ptr == 0) gen_swap_stack (); gen_push (HL_REG); nargs = nargs + INTSIZE; if (!match (",")) break; } needbrack (")"); if (aflag) gnargs(nargs / INTSIZE); if (ptr) gen_call (ptr); else callstk (); stkp = gen_modify_stack (stkp + nargs); }
/** * "switch" statement */ void doswitch(void) { WHILE ws; WHILE *ptr; ws.symbol_idx = local_table_index; ws.stack_pointer = stkp; ws.type = WSSWITCH; ws.case_test = swstp; ws.body_tab = getlabel (); ws.incr_def = ws.while_exit = getlabel (); addwhile (&ws); gen_immediate (); print_label (ws.body_tab); newline (); gen_push (HL_REG); needbrack ("("); expression (YES); needbrack (")"); stkp = stkp + INTSIZE; // '?case' will adjust the stack gen_jump_case (); statement (NO); ptr = readswitch (); gen_jump (ptr->while_exit); dumpsw (ptr); generate_label (ptr->while_exit); local_table_index = ptr->symbol_idx; stkp = gen_modify_stack (ptr->stack_pointer); swstp = ptr->case_test; delwhile (); }
/** * divide the primary register by INTSIZE, never used */ void gen_divide_by_two(void) { gen_push(HL_REG); /* push primary in prep for gasr */ gen_immediate (); output_number (1); newline (); gen_arithm_shift_right (); /* divide by two */ }
/** * "switch" statement */ doswitch() { loop_t loop; loop_t *ptr; loop.symbol_idx = local_table_index; loop.stack_pointer = stkp; loop.type = WSSWITCH; loop.test_label = swstp; loop.body_label = getlabel (); loop.cont_label = loop.exit_label = getlabel (); addloop (&loop); gen_immediate_a (); print_label (loop.body_label); newline (); gen_push (); needbrack ("("); expression (YES); needbrack (")"); stkp = stkp + INTSIZE; // '?case' will adjust the stack gen_jump_case (); statement (NO); ptr = readswitch (); gen_jump (ptr->exit_label); dumpsw (ptr); generate_label (ptr->exit_label); local_table_index = ptr->symbol_idx; stkp = gen_modify_stack (ptr->stack_pointer); swstp = ptr->test_label; delloop (); }
AMODE *temp_float(void) /* * allocate a temporary address register and return it's * addressing mode. */ { AMODE *ap; ap = xalloc(sizeof(AMODE)); ap->mode = am_freg; ap->preg = next_float % cf_freefloat; if( next_float > max_float ) { gen_push(ap->preg,am_freg,0); fregs[ap->preg] = 1; regstack[rsdepth++] = ap->preg+16; max_addr = next_float; } ++next_float; return ap; }
AMODE *temp_addr(void) /* * allocate a temporary address register and return it's * addressing mode. */ { AMODE *ap; ap = xalloc(sizeof(AMODE)); ap->mode = am_areg; ap->preg = next_addr % cf_freeaddress; if( next_addr > max_addr ) { gen_push(ap->preg,am_areg,0); aregs[ap->preg] = 1; regstack[rsdepth++] = ap->preg+8; max_addr = next_addr; } ++next_addr; return ap; }
AMODE *temp_data(void) /* * allocate a temporary data register and return it's * addressing mode. */ { AMODE *ap; ap = xalloc(sizeof(AMODE)); ap->mode = am_dreg; ap->preg = next_data % cf_freedata; if( next_data > max_data ) { gen_push(ap->preg,am_dreg,0); dregs[ap->preg] = 1; regstack[rsdepth++] = ap->preg; max_data = next_data; } ++next_data; return ap; }
void Compiler::handle_ik_ls(const JInst& jinst) { switch(jinst.opcode) { case OPCODE_ICONST_M1: gen_push((int)-1); break; case OPCODE_ICONST_0: gen_push((int)0); break; case OPCODE_ICONST_1: gen_push((int)1); break; case OPCODE_ICONST_2: gen_push((int)2); break; case OPCODE_ICONST_3: gen_push((int)3); break; case OPCODE_ICONST_4: gen_push((int)4); break; case OPCODE_ICONST_5: gen_push((int)5); break; case OPCODE_LCONST_0: gen_push((jlong)0); break; case OPCODE_LCONST_1: gen_push((jlong)1); break; case OPCODE_FCONST_0: gen_push(flt32, &g_fconst_0); break; case OPCODE_FCONST_1: gen_push(flt32, &g_fconst_1); break; case OPCODE_FCONST_2: gen_push(flt32, &g_fconst_2); break; case OPCODE_DCONST_0: gen_push(dbl64, &g_dconst_0); break; case OPCODE_DCONST_1: gen_push(dbl64, &g_dconst_1); break; case OPCODE_LDC: case OPCODE_LDC_W: case OPCODE_LDC2_W: gen_ldc(); break; case OPCODE_SIPUSH: gen_push((int)(short)(unsigned short)jinst.op0); break; case OPCODE_BIPUSH: gen_push((int)(char)(unsigned char)jinst.op0); break; case OPCODE_ASTORE: assert(m_jframe->top() == jobj || m_jframe->top() == jretAddr); gen_st(m_jframe->top(), jinst.op0); break; case OPCODE_ISTORE: gen_st(i32, jinst.op0); break; case OPCODE_LSTORE: gen_st(i64, jinst.op0); break; case OPCODE_FSTORE: gen_st(flt32, jinst.op0); break; case OPCODE_DSTORE: gen_st(dbl64, jinst.op0); break; case OPCODE_ISTORE_0: case OPCODE_ISTORE_1: case OPCODE_ISTORE_2: case OPCODE_ISTORE_3: gen_st(i32, jinst.opcode-OPCODE_ISTORE_0); break; case OPCODE_LSTORE_0: case OPCODE_LSTORE_1: case OPCODE_LSTORE_2: case OPCODE_LSTORE_3: gen_st(i64, jinst.opcode-OPCODE_LSTORE_0); break; case OPCODE_FSTORE_0: case OPCODE_FSTORE_1: case OPCODE_FSTORE_2: case OPCODE_FSTORE_3: gen_st(flt32, jinst.opcode-OPCODE_FSTORE_0); break; case OPCODE_DSTORE_0: case OPCODE_DSTORE_1: case OPCODE_DSTORE_2: case OPCODE_DSTORE_3: gen_st(dbl64, jinst.opcode-OPCODE_DSTORE_0); break; case OPCODE_ASTORE_0: case OPCODE_ASTORE_1: case OPCODE_ASTORE_2: case OPCODE_ASTORE_3: assert(m_jframe->top() == jobj || m_jframe->top() == jretAddr); gen_st(m_jframe->top(), jinst.opcode-OPCODE_ASTORE_0); break; case OPCODE_ILOAD: gen_ld(i32, jinst.op0); break; case OPCODE_LLOAD: gen_ld(i64, jinst.op0); break; case OPCODE_FLOAD: gen_ld(flt32, jinst.op0); break; case OPCODE_DLOAD: gen_ld(dbl64, jinst.op0); break; case OPCODE_ALOAD: gen_ld(jobj, jinst.op0); break; case OPCODE_ILOAD_0: case OPCODE_ILOAD_1: case OPCODE_ILOAD_2: case OPCODE_ILOAD_3: gen_ld(i32, jinst.opcode-OPCODE_ILOAD_0); break; case OPCODE_LLOAD_0: case OPCODE_LLOAD_1: case OPCODE_LLOAD_2: case OPCODE_LLOAD_3: gen_ld(i64, jinst.opcode-OPCODE_LLOAD_0); break; case OPCODE_FLOAD_0: case OPCODE_FLOAD_1: case OPCODE_FLOAD_2: case OPCODE_FLOAD_3: gen_ld(flt32, jinst.opcode-OPCODE_FLOAD_0); break; case OPCODE_DLOAD_0: case OPCODE_DLOAD_1: case OPCODE_DLOAD_2: case OPCODE_DLOAD_3: gen_ld(dbl64, jinst.opcode-OPCODE_DLOAD_0); break; case OPCODE_ALOAD_0: case OPCODE_ALOAD_1: case OPCODE_ALOAD_2: case OPCODE_ALOAD_3: gen_ld(jobj, jinst.opcode-OPCODE_ALOAD_0); break; case OPCODE_ACONST_NULL: gen_push(jobj, NULL_REF); break; default: assert(false); break; } }
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); } }
/** * declare local variables * works just like "declglb", but modifies machine stack and adds * symbol table entry with appropriate stack offset to find it again * @param typ * @param stclass * @param otag index of tag in tag_table */ void declare_local(int typ, int stclass, int otag) { int k, j; char sname[NAMESIZE]; FOREVER { FOREVER { if (endst()) return; if (match("*")) j = POINTER; else j = VARIABLE; if (!symname(sname)) illname(); if (-1 != find_locale(sname)) multidef (sname); if (match("[")) { k = needsub(); if (k) { j = ARRAY; if (typ & CINT) { k = k * INTSIZE; } else if (typ == STRUCT) { k = k * tag_table[otag].size; } } else { j = POINTER; k = INTSIZE; } } else { if (j == POINTER) { k = INTSIZE; } else { switch (typ) { case CCHAR: case UCHAR: k = 1; break; case STRUCT: k = tag_table[otag].size; break; default: k = INTSIZE; } } } if (stclass == LSTATIC) { add_local(sname, j, typ, k, LSTATIC); break; } if (stclass == REGISTER) { int r = gen_register(j, k, typ); if (r != -1) { add_local(sname, j, typ, r, REGISTER); break; } } if (match("=")) { gen_modify_stack(stkp); expression(0); gen_push(0); } else stkp = gen_defer_modify_stack(stkp - k); add_local(sname, j, typ, stkp, AUTO); break; } if (!match(",")) return; } }
void gen() { int i, j, n; /* so far, we have no moves for the current ply */ first_move[ply + 1] = first_move[ply]; for (i = 0; i < 64; ++i) if (color[i] == side) { if (piece[i] == PAWN) { if (side == LIGHT) { if (COL(i) != 0 && color[i - 9] == DARK) gen_push(i, i - 9, 17); if (COL(i) != 7 && color[i - 7] == DARK) gen_push(i, i - 7, 17); if (color[i - 8] == EMPTY) { gen_push(i, i - 8, 16); if (i >= 48 && color[i - 16] == EMPTY) gen_push(i, i - 16, 24); } } else { if (COL(i) != 0 && color[i + 7] == LIGHT) gen_push(i, i + 7, 17); if (COL(i) != 7 && color[i + 9] == LIGHT) gen_push(i, i + 9, 17); if (color[i + 8] == EMPTY) { gen_push(i, i + 8, 16); if (i <= 15 && color[i + 16] == EMPTY) gen_push(i, i + 16, 24); } } } else for (j = 0; j < offsets[piece[i]]; ++j) for (n = i;;) { n = mailbox[mailbox64[n] + offset[piece[i]][j]]; if (n == -1) break; if (color[n] != EMPTY) { if (color[n] == xside) gen_push(i, n, 1); break; } gen_push(i, n, 0); if (!slide[piece[i]]) break; } } /* generate castle moves */ if (side == LIGHT) { if (castle & 1) gen_push(E1, G1, 2); if (castle & 2) gen_push(E1, C1, 2); } else { if (castle & 4) gen_push(E8, G8, 2); if (castle & 8) gen_push(E8, C8, 2); } /* generate en passant moves */ if (ep != -1) { if (side == LIGHT) { if (COL(ep) != 0 && color[ep + 7] == LIGHT && piece[ep + 7] == PAWN) gen_push(ep + 7, ep, 21); if (COL(ep) != 7 && color[ep + 9] == LIGHT && piece[ep + 9] == PAWN) gen_push(ep + 9, ep, 21); } else { if (COL(ep) != 0 && color[ep - 9] == DARK && piece[ep - 9] == PAWN) gen_push(ep - 9, ep, 21); if (COL(ep) != 7 && color[ep - 7] == DARK && piece[ep - 7] == PAWN) gen_push(ep - 7, ep, 21); } } }
void gen_caps() { int i, j, n; first_move[ply + 1] = first_move[ply]; for (i = 0; i < 64; ++i) if (color[i] == side) { if (piece[i]==PAWN) { if (side == LIGHT) { if (COL(i) != 0 && color[i - 9] == DARK) gen_push(i, i - 9, 17); if (COL(i) != 7 && color[i - 7] == DARK) gen_push(i, i - 7, 17); if (i <= 15 && color[i - 8] == EMPTY) gen_push(i, i - 8, 16); } if (side == DARK) { if (COL(i) != 0 && color[i + 7] == LIGHT) gen_push(i, i + 7, 17); if (COL(i) != 7 && color[i + 9] == LIGHT) gen_push(i, i + 9, 17); if (i >= 48 && color[i + 8] == EMPTY) gen_push(i, i + 8, 16); } } else for (j = 0; j < offsets[piece[i]]; ++j) for (n = i;;) { n = mailbox[mailbox64[n] + offset[piece[i]][j]]; if (n == -1) break; if (color[n] != EMPTY) { if (color[n] == xside) gen_push(i, n, 1); break; } if (!slide[piece[i]]) break; } } if (ep != -1) { if (side == LIGHT) { if (COL(ep) != 0 && color[ep + 7] == LIGHT && piece[ep + 7] == PAWN) gen_push(ep + 7, ep, 21); if (COL(ep) != 7 && color[ep + 9] == LIGHT && piece[ep + 9] == PAWN) gen_push(ep + 9, ep, 21); } else { if (COL(ep) != 0 && color[ep - 9] == DARK && piece[ep - 9] == PAWN) gen_push(ep - 9, ep, 21); if (COL(ep) != 7 && color[ep - 7] == DARK && piece[ep - 7] == PAWN) gen_push(ep - 7, ep, 21); } } }