Commit 211e6d2c authored by Recolic Keghart's avatar Recolic Keghart
Browse files

Merge branch 'reconstruct-helpers' into 'pa2'

Reconstruct helpers

See merge request !1
parents 3949ce4c f6760515
......@@ -75,47 +75,48 @@ extern DecodeInfo decoding;
#define id_src2 (&decoding.src2)
#define id_dest (&decoding.dest)
#define make_DHelper_funcname(name) concat(decode_, name)
#define make_DHelper(name) void make_DHelper_funcname(name) (vaddr_t *eip)
#define make_DHelper(name) void name (vaddr_t *eip)
typedef void (*DHelper) (vaddr_t *);
make_DHelper(I2E);
make_DHelper(I2a);
make_DHelper(I2r);
make_DHelper(SI2E);
make_DHelper(SI_E2G);
make_DHelper(I_E2G);
make_DHelper(I_G2E);
make_DHelper(I);
make_DHelper(r);
make_DHelper(E);
make_DHelper(setcc_E);
make_DHelper(gp7_E);
make_DHelper(test_I);
make_DHelper(SI);
make_DHelper(G2E);
make_DHelper(E2G);
make_DHelper(mov_I2r);
make_DHelper(mov_I2E);
make_DHelper(mov_G2E);
make_DHelper(mov_E2G);
make_DHelper(lea_M2G);
make_DHelper(gp2_1_E);
make_DHelper(gp2_cl2E);
make_DHelper(gp2_Ib2E);
make_DHelper(O2a);
make_DHelper(a2O);
make_DHelper(J);
make_DHelper(push_SI);
make_DHelper(in_I2a);
make_DHelper(in_dx2a);
make_DHelper(out_a2I);
make_DHelper(out_a2dx);
namespace DHelperImpl {
make_DHelper(I2E);
make_DHelper(I2a);
make_DHelper(I2r);
make_DHelper(SI2E);
make_DHelper(SI_E2G);
make_DHelper(I_E2G);
make_DHelper(I_G2E);
make_DHelper(I);
make_DHelper(r);
make_DHelper(E);
make_DHelper(setcc_E);
make_DHelper(gp7_E);
make_DHelper(test_I);
make_DHelper(SI);
make_DHelper(G2E);
make_DHelper(E2G);
make_DHelper(mov_I2r);
make_DHelper(mov_I2E);
make_DHelper(mov_G2E);
make_DHelper(mov_E2G);
make_DHelper(lea_M2G);
make_DHelper(gp2_1_E);
make_DHelper(gp2_cl2E);
make_DHelper(gp2_Ib2E);
make_DHelper(O2a);
make_DHelper(a2O);
make_DHelper(J);
make_DHelper(push_SI);
make_DHelper(in_I2a);
make_DHelper(in_dx2a);
make_DHelper(out_a2I);
make_DHelper(out_a2dx);
}
#endif
......@@ -3,8 +3,7 @@
#include "nemu.h"
#define make_EHelper_funcname(name) concat(exec_, name)
#define make_EHelper(name) void make_EHelper_funcname(name) (vaddr_t *eip)
#define make_EHelper(name) void name(vaddr_t *eip)
typedef void (*EHelper) (vaddr_t *);
#include "cpu/decode.h"
......
......@@ -217,7 +217,7 @@ static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
// eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
RLIB_MACRO_DEBUG_ASSERT((unsigned)width < 5);
static const uint32_t niddles [5] {0, 0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff};
cpu_eflags::get<cpu_eflags::ZF>() = (*result & niddles[width]);
cpu_eflags::get<cpu_eflags::ZF>() = !(*result & niddles[width]);
}
static inline void rtl_update_SF(const rtlreg_t* result, int width) {
......
......@@ -9,320 +9,327 @@ void decoding_set_jmp(bool is_jmp) {
decoding.is_jmp = is_jmp;
}
#define make_DopHelper_funcname(name) concat(decode_op_, name)
#define make_DopHelper(name) void make_DopHelper_funcname(name) (vaddr_t *eip, Operand *op, bool load_val)
/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
/* Ib, Iv */
static inline make_DopHelper(I) {
/* eip here is pointing to the immediate */
op->type = OP_TYPE_IMM;
op->imm = instr_fetch(eip, op->width);
rtl_li(&op->val, op->imm);
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "$0x%x", op->imm);
#endif
}
/* I386 manual does not contain this abbreviation, but it is different from
* the one above from the view of implementation. So we use another helper
* function to decode it.
*/
/* sign immediate */
static inline make_DopHelper(SI) {
assert(op->width == 1 || op->width == 4);
op->type = OP_TYPE_IMM;
/* TODO: Use instr_fetch() to read `op->width' bytes of memory
* pointed by `eip'. Interpret the result as a signed immediate,
* and assign it to op->simm.
*
op->simm = ???
#define make_DopHelper_funcname(name) DopHelperImpl::name
#define make_DopHelper(name) void name (vaddr_t *eip, Operand *op, bool load_val)
namespace DopHelperImpl {
/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
/* Ib, Iv */
static inline make_DopHelper(I) {
/* eip here is pointing to the immediate */
op->type = OP_TYPE_IMM;
op->imm = instr_fetch(eip, op->width);
rtl_li(&op->val, op->imm);
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "$0x%x", op->imm);
#endif
}
/* I386 manual does not contain this abbreviation, but it is different from
* the one above from the view of implementation. So we use another helper
* function to decode it.
*/
op->simm = instr_fetch(eip, op->width);
rtl_li(&op->val, op->simm);
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "$0x%x", op->simm);
#endif
}
/* I386 manual does not contain this abbreviation.
* It is convenient to merge them into a single helper function.
*/
/* AL/eAX */
static inline make_DopHelper(a) {
op->type = OP_TYPE_REG;
op->reg = R_EAX;
if (load_val) {
rtl_lr(&op->val, R_EAX, op->width);
/* sign immediate */
static inline make_DopHelper(SI) {
assert(op->width == 1 || op->width == 4);
op->type = OP_TYPE_IMM;
/* TODO: Use instr_fetch() to read `op->width' bytes of memory
* pointed by `eip'. Interpret the result as a signed immediate,
* and assign it to op->simm.
*
op->simm = ???
*/
op->simm = instr_fetch(eip, op->width);
rtl_li(&op->val, op->simm);
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "$0x%x", op->simm);
#endif
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(R_EAX, op->width));
#endif
}
/* This helper function is use to decode register encoded in the opcode. */
/* XX: AL, AH, BL, BH, CL, CH, DL, DH
* eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI
*/
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = decoding.opcode & 0x7;
if (load_val) {
rtl_lr(&op->val, op->reg, op->width);
/* I386 manual does not contain this abbreviation.
* It is convenient to merge them into a single helper function.
*/
/* AL/eAX */
static inline make_DopHelper(a) {
op->type = OP_TYPE_REG;
op->reg = R_EAX;
if (load_val) {
rtl_lr(&op->val, R_EAX, op->width);
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(R_EAX, op->width));
#endif
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(op->reg, op->width));
#endif
}
/* I386 manual does not contain this abbreviation.
* We decode everything of modR/M byte by one time.
*/
/* Eb, Ew, Ev
* Gb, Gv
* Cd,
* M
* Rd
* Sw
*/
static inline void make_DopHelper_funcname(rm)(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
read_ModR_M(eip, rm, load_rm_val, reg, load_reg_val);
}
/* Ob, Ov */
static inline make_DopHelper(O) {
op->type = OP_TYPE_MEM;
rtl_li(&op->addr, instr_fetch(eip, 4));
if (load_val) {
rtl_lm(&op->val, &op->addr, op->width);
/* This helper function is use to decode register encoded in the opcode. */
/* XX: AL, AH, BL, BH, CL, CH, DL, DH
* eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI
*/
static inline make_DopHelper(r) {
op->type = OP_TYPE_REG;
op->reg = decoding.opcode & 0x7;
if (load_val) {
rtl_lr(&op->val, op->reg, op->width);
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "%%%s", reg_name(op->reg, op->width));
#endif
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "0x%x", op->addr);
#endif
}
/* Eb <- Gb
* Ev <- Gv
*/
make_DHelper(G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, id_src, true);
}
make_DHelper(mov_G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, id_src, true);
}
/* Gb <- Eb
* Gv <- Ev
*/
make_DHelper(E2G) {
make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, true);
}
make_DHelper(mov_E2G) {
make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, false);
}
make_DHelper(lea_M2G) {
make_DopHelper_funcname(rm)(eip, id_src, false, id_dest, false);
}
/* AL <- Ib
* eAX <- Iv
*/
make_DHelper(I2a) {
make_DopHelper_funcname(a)(eip, id_dest, true);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Gv <- EvIb
* Gv <- EvIv
* use for imul */
make_DHelper(I_E2G) {
make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Eb <- Ib
* Ev <- Iv
*/
make_DHelper(I2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
make_DHelper(mov_I2E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* XX <- Ib
* eXX <- Iv
*/
make_DHelper(I2r) {
make_DopHelper_funcname(r)(eip, id_dest, true);
make_DopHelper_funcname(I)(eip, id_src, true);
}
make_DHelper(mov_I2r) {
make_DopHelper_funcname(r)(eip, id_dest, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* used by unary operations */
make_DHelper(I) {
make_DopHelper_funcname(I)(eip, id_dest, true);
}
make_DHelper(r) {
make_DopHelper_funcname(r)(eip, id_dest, true);
}
make_DHelper(E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
}
make_DHelper(setcc_E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
}
make_DHelper(gp7_E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
}
/* used by test in group3 */
make_DHelper(test_I) {
make_DopHelper_funcname(I)(eip, id_src, true);
}
make_DHelper(SI2E) {
assert(id_dest->width == 2 || id_dest->width == 4);
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
id_src->width = 1;
make_DopHelper_funcname(SI)(eip, id_src, true);
if (id_dest->width == 2) {
id_src->val &= 0xffff;
/* I386 manual does not contain this abbreviation.
* We decode everything of modR/M byte by one time.
*/
/* Eb, Ew, Ev
* Gb, Gv
* Cd,
* M
* Rd
* Sw
*/
static inline void rm(vaddr_t *eip, Operand *rm, bool load_rm_val, Operand *reg, bool load_reg_val) {
read_ModR_M(eip, rm, load_rm_val, reg, load_reg_val);
}
}
make_DHelper(SI_E2G) {
assert(id_dest->width == 2 || id_dest->width == 4);
make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false);
id_src->width = 1;
make_DopHelper_funcname(SI)(eip, id_src, true);
if (id_dest->width == 2) {
id_src->val &= 0xffff;
/* Ob, Ov */
static inline make_DopHelper(O) {
op->type = OP_TYPE_MEM;
rtl_li(&op->addr, instr_fetch(eip, 4));
if (load_val) {
rtl_lm(&op->val, &op->addr, op->width);
}
#ifdef DEBUG
snprintf(op->str, OP_STR_SIZE, "0x%x", op->addr);
#endif
}
}
} // end namespace DopHelperImpl
make_DHelper(gp2_1_E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
id_src->type = OP_TYPE_IMM;
id_src->imm = 1;
rtl_li(&id_src->val, 1);
#ifdef DEBUG
sprintf(id_src->str, "$1");
#endif
}
make_DHelper(gp2_cl2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
id_src->type = OP_TYPE_REG;
id_src->reg = R_CL;
rtl_lr(&id_src->val, R_CL, 1);
#ifdef DEBUG
sprintf(id_src->str, "%%cl");
#endif
}
make_DHelper(gp2_Ib2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
id_src->width = 1;
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Ev <- GvIb
* use for shld/shrd */
make_DHelper(Ib_G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true);
id_src->width = 1;
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Ev <- GvCL
* use for shld/shrd */
make_DHelper(cl_G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, id_src2, true);
id_src->type = OP_TYPE_REG;
id_src->reg = R_CL;
rtl_lr(&id_src->val, R_CL, 1);
#ifdef DEBUG
sprintf(id_src->str, "%%cl");
#endif
}
make_DHelper(O2a) {
make_DopHelper_funcname(O)(eip, id_src, true);
make_DopHelper_funcname(a)(eip, id_dest, false);
}
make_DHelper(a2O) {
make_DopHelper_funcname(a)(eip, id_src, true);
make_DopHelper_funcname(O)(eip, id_dest, false);
}
make_DHelper(J) {
make_DopHelper_funcname(SI)(eip, id_dest, false);
// the target address can be computed in the decode stage
decoding.jmp_eip = id_dest->simm + *eip;
}
make_DHelper(push_SI) {
make_DopHelper_funcname(SI)(eip, id_dest, true);
}
make_DHelper(in_I2a) {
id_src->width = 1;
make_DopHelper_funcname(I)(eip, id_src, true);
make_DopHelper_funcname(a)(eip, id_dest, false);
}
make_DHelper(in_dx2a) {
id_src->type = OP_TYPE_REG;
id_src->reg = R_DX;
rtl_lr(&id_src->val, R_DX, 2);
#ifdef DEBUG
sprintf(id_src->str, "(%%dx)");
#endif
make_DopHelper_funcname(a)(eip, id_dest, false);
}
make_DHelper(out_a2I) {
make_DopHelper_funcname(a)(eip, id_src, true);
id_dest->width = 1;
make_DopHelper_funcname(I)(eip, id_dest, true);
}
namespace DHelperImpl {
make_DHelper(out_a2dx) {
make_DopHelper_funcname(a)(eip, id_src, true);
id_dest->type = OP_TYPE_REG;
id_dest->reg = R_DX;
rtl_lr(&id_dest->val, R_DX, 2);
#ifdef DEBUG
sprintf(id_dest->str, "(%%dx)");
#endif
}
/* Eb <- Gb
* Ev <- Gv
*/
make_DHelper(G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, id_src, true);
}
make_DHelper(mov_G2E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, id_src, true);
}
/* Gb <- Eb
* Gv <- Ev
*/
make_DHelper(E2G) {
make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, true);
}
make_DHelper(mov_E2G) {
make_DopHelper_funcname(rm)(eip, id_src, true, id_dest, false);
}
make_DHelper(lea_M2G) {
make_DopHelper_funcname(rm)(eip, id_src, false, id_dest, false);
}
/* AL <- Ib
* eAX <- Iv
*/
make_DHelper(I2a) {
make_DopHelper_funcname(a)(eip, id_dest, true);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Gv <- EvIb
* Gv <- EvIv
* use for imul */
make_DHelper(I_E2G) {
make_DopHelper_funcname(rm)(eip, id_src2, true, id_dest, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* Eb <- Ib
* Ev <- Iv
*/
make_DHelper(I2E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
make_DHelper(mov_I2E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* XX <- Ib
* eXX <- Iv
*/
make_DHelper(I2r) {
make_DopHelper_funcname(r)(eip, id_dest, true);
make_DopHelper_funcname(I)(eip, id_src, true);
}
make_DHelper(mov_I2r) {
make_DopHelper_funcname(r)(eip, id_dest, false);
make_DopHelper_funcname(I)(eip, id_src, true);
}
/* used by unary operations */
make_DHelper(I) {
make_DopHelper_funcname(I)(eip, id_dest, true);
}
make_DHelper(r) {
make_DopHelper_funcname(r)(eip, id_dest, true);
}
make_DHelper(E) {
make_DopHelper_funcname(rm)(eip, id_dest, true, NULL, false);
}
make_DHelper(setcc_E) {
make_DopHelper_funcname(rm)(eip, id_dest, false, NULL, false);