2019-06-17 20:59:30 +02:00
|
|
|
// The OS/K Team licenses this file to you under the MIT license.
|
|
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
|
|
|
|
#include <pc/arch.h>
|
2019-07-02 20:13:05 +02:00
|
|
|
#include <in/arch_i.h>
|
2019-06-17 20:59:30 +02:00
|
|
|
|
2019-06-21 22:19:55 +02:00
|
|
|
bool eval_cond(ctx_t *ctx, uint cond)
|
2019-06-17 20:59:30 +02:00
|
|
|
{
|
|
|
|
bool neg = cond & (1 << 4);
|
|
|
|
bool ok;
|
|
|
|
|
|
|
|
cond &= ~(1 << 4);
|
|
|
|
|
|
|
|
switch (cond)
|
|
|
|
{
|
|
|
|
case CD_NONE: ok = 1; break;
|
|
|
|
|
|
|
|
case CD_C: ok = flg&CF; break;
|
|
|
|
case CD_O: ok = flg&OF; break;
|
|
|
|
case CD_Z: ok = flg&ZF; break;
|
|
|
|
case CD_S: ok = flg&SF; break;
|
|
|
|
case CD_P: ok = flg&PF; break;
|
|
|
|
|
|
|
|
case CD_A: ok = !(flg&CF || flg&ZF); break;
|
|
|
|
case CD_AE: ok = !(flg&CF); break;
|
|
|
|
|
|
|
|
case CD_B: ok = flg&CF; break;
|
|
|
|
case CD_BE: ok = flg&CF || flg&ZF; break;
|
|
|
|
|
|
|
|
case CD_G: ok = !(flg&ZF) && (!(flg&SF) == !(flg&OF)); break;
|
|
|
|
case CD_GE: ok = !(flg&SF) == !(flg&OF); break;
|
|
|
|
|
|
|
|
case CD_L: ok = !(flg&SF) != !(flg&OF); break;
|
|
|
|
case CD_LE: ok = flg&ZF || (!(flg&SF) != !(flg&OF)); break;
|
|
|
|
|
|
|
|
case CD_CXZ: ok = !rcx; break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
_except(ctx, E_ILL, "Invalid COND value: 0x%x", (neg?cond|(1<<4):cond));
|
|
|
|
}
|
|
|
|
|
|
|
|
return neg ? !ok : !!ok;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Executes an instruction
|
|
|
|
//
|
|
|
|
void exec_instr(ctx_t *ctx,
|
|
|
|
instr_t *in,
|
|
|
|
acc_t *p1,
|
|
|
|
acc_t *p2,
|
2019-07-01 21:46:36 +02:00
|
|
|
acc_t *p3,
|
2019-06-17 20:59:30 +02:00
|
|
|
bool lock,
|
2019-07-02 20:13:05 +02:00
|
|
|
bool rep)
|
2019-06-17 20:59:30 +02:00
|
|
|
{
|
2019-07-09 21:02:26 +02:00
|
|
|
uint out;
|
2019-07-01 21:46:36 +02:00
|
|
|
ulong r1 = 0, r2 = 0, r3 = 0;
|
2019-06-17 20:59:30 +02:00
|
|
|
|
2019-06-23 21:12:25 +02:00
|
|
|
// Global instruction counter
|
2019-07-08 17:46:10 +02:00
|
|
|
fc0++;
|
2019-06-21 22:19:55 +02:00
|
|
|
|
2019-06-23 21:12:25 +02:00
|
|
|
// Current frame instruction counter
|
2019-07-04 20:33:49 +02:00
|
|
|
fc2++; // since last frame change
|
|
|
|
fc1++; // since startup
|
2019-06-23 21:12:25 +02:00
|
|
|
|
2019-06-17 20:59:30 +02:00
|
|
|
//
|
|
|
|
// For REPs we evaluate the condition AFTER running the instruction,
|
|
|
|
// in a do ... while(cond) fashion
|
|
|
|
//
|
2019-07-02 20:13:05 +02:00
|
|
|
if (ctx->cond && in->func != i_b) // 'B' instruction is special
|
|
|
|
if (!rep && !eval_cond(ctx, ctx->cond))
|
|
|
|
return;
|
2019-06-28 19:18:53 +02:00
|
|
|
|
2019-07-04 20:33:49 +02:00
|
|
|
if (ctx->dumpsw)
|
|
|
|
dump_instr(ctx, in, p1, p2, p3, lock, rep);
|
2019-06-17 20:59:30 +02:00
|
|
|
|
|
|
|
do_rep:
|
|
|
|
|
2019-07-01 21:46:36 +02:00
|
|
|
out = in->func(ctx, p1, p2, p3, &r1, &r2, &r3);
|
2019-06-17 20:59:30 +02:00
|
|
|
|
2019-07-09 21:02:26 +02:00
|
|
|
#define OUTPUT(p, r) { \
|
|
|
|
if (p->type == A_REG) \
|
|
|
|
R(p->reg) = r1; \
|
|
|
|
else if (p1->type == A_IMM64) \
|
|
|
|
_except(ctx, E_ACC, "Trying to output to an IMM64"); \
|
|
|
|
else { \
|
|
|
|
assert(ACC_IS_MEM(p)); \
|
|
|
|
writemem(ctx, r, p->addr, p->mlen); \
|
|
|
|
} }
|
2019-06-17 20:59:30 +02:00
|
|
|
|
|
|
|
|
2019-07-09 21:02:26 +02:00
|
|
|
if (out)
|
2019-07-01 21:46:36 +02:00
|
|
|
{
|
2019-07-09 21:02:26 +02:00
|
|
|
OUTPUT(p1, r1);
|
|
|
|
if (out >= 2) OUTPUT(p2, r2);
|
|
|
|
if (out >= 3) OUTPUT(p3, r3);
|
2019-07-01 21:46:36 +02:00
|
|
|
}
|
|
|
|
|
2019-06-17 20:59:30 +02:00
|
|
|
if (rep)
|
|
|
|
{
|
|
|
|
// RCX remains untouched when condition fails
|
2019-07-02 20:13:05 +02:00
|
|
|
if (!eval_cond(ctx, ctx->cond))
|
2019-06-17 20:59:30 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (rcx > 0)
|
|
|
|
rcx--;
|
|
|
|
|
|
|
|
if (rcx == 0)
|
|
|
|
return;
|
|
|
|
|
2019-07-08 17:46:10 +02:00
|
|
|
// Should we really count REP's in instruction count?
|
|
|
|
fc0++;
|
|
|
|
fc1++;
|
|
|
|
fc2++;
|
2019-06-21 22:19:55 +02:00
|
|
|
|
2019-07-04 20:33:49 +02:00
|
|
|
#if 0
|
2019-06-17 20:59:30 +02:00
|
|
|
// Show that we're REP'ing
|
2019-07-04 20:33:49 +02:00
|
|
|
if (ctx->dumpsw)
|
|
|
|
dump_instr(ctx, in, p1, p2, p3, lock, rep);
|
2019-06-21 22:19:55 +02:00
|
|
|
#endif
|
2019-06-17 20:59:30 +02:00
|
|
|
|
|
|
|
goto do_rep;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|