wip! implement BAL, PUSH, POP(RET)
This commit is contained in:
parent
7b0d3b1a53
commit
3382fc1700
2 changed files with 124 additions and 0 deletions
|
|
@ -257,6 +257,21 @@ JCOND 0000 1010 cond:4 ra:4
|
|||
|
||||
EXCP 0000 0000 1100 id:4
|
||||
|
||||
&bal dest
|
||||
|
||||
@bal .... .... dest:23 . &bal
|
||||
#@bal_3a .... .... .... .... .... p1_1916:4 p2:4 p1_2320:4 p1_1501:15 .
|
||||
|
||||
BAL_ra 1100 0000 .... .... .... .... .... ...- @bal # fmt 5
|
||||
#BAL_rp 0000 0000 1000 0000 0010 .... .... .... .... .... .... .... @bal_3a # fmt 3a
|
||||
|
||||
&pop rt ra count dest
|
||||
@pop .... ... rt:1 ra:1 count:3 dest:4 &pop
|
||||
&push ra count src
|
||||
@push .... .... ra:1 count:3 src:4 &push
|
||||
|
||||
pop 0000 001. .... .... @pop # fmt 14, includes popret via rt bit
|
||||
push 0000 0001 .... .... @push # fmt 14
|
||||
|
||||
### Load and Store ###
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "exec/translator.h"
|
||||
#include "accel/tcg/cpu-ldst.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "tcg/tcg-cond.h"
|
||||
#include "tcg/tcg-op-common.h"
|
||||
#include "tcg/tcg-op.h"
|
||||
|
|
@ -37,6 +38,27 @@ enum {
|
|||
CR16C_COND_UC,
|
||||
};
|
||||
|
||||
/* Representation of register pair encoding */
|
||||
enum {
|
||||
CR16C_RP_R1R0,
|
||||
CR16C_RP_R2R1,
|
||||
CR16C_RP_R3R2,
|
||||
CR16C_RP_R4R3,
|
||||
CR16C_RP_R5R4,
|
||||
CR16C_RP_R6R5,
|
||||
CR16C_RP_R7R6,
|
||||
CR16C_RP_R8R7,
|
||||
CR16C_RP_R9R8,
|
||||
CR16C_RP_R10R9,
|
||||
CR16C_RP_R11R10,
|
||||
CR16C_RP_R12LR11,
|
||||
// TODO these are ~funky, depend on CFG.SR and PSR.U
|
||||
/*CR16C_RP_R12,
|
||||
CR16C_RP_R13,
|
||||
CR16C_RP_RA,
|
||||
CR16C_RP_SP,*/
|
||||
};
|
||||
|
||||
typedef struct DisasContext {
|
||||
DisasContextBase base;
|
||||
CPUCR16CState* env;
|
||||
|
|
@ -1460,6 +1482,93 @@ static bool trans_STORM(DisasContext *ctx, arg_STORM *a) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool trans_BAL_ra(DisasContext *ctx, arg_BAL_ra *a) {
|
||||
#define BAL_LEN 4
|
||||
// TODO BAL_rp would be 3 words/6 bytes (fmt 3a)
|
||||
vaddr pc_this = ctx->base.pc_next - BAL_LEN;
|
||||
vaddr dest_offset = a->dest*2;
|
||||
qemu_printf("!!!bal %04lx dest=%d\n", pc_this, a->dest);
|
||||
|
||||
// 1) store next PC in ra TODO BAL_rp can choose where
|
||||
tcg_gen_movi_i32(r[CR16C_REGNO_RA], ctx->base.pc_next);
|
||||
|
||||
// 2) sign extend from 23 -> "25" bits
|
||||
int32_t dest_sextend = sextract32(dest_offset, 0, 23);
|
||||
|
||||
qemu_printf("=> 0x%lx\n", pc_this + dest_sextend);
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
gen_goto(&ctx->base, pc_this + dest_sextend, 0);
|
||||
|
||||
// TODO IAD trap
|
||||
// TODO CFG.SR handling
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_pop(DisasContext *ctx, arg_pop *a) {
|
||||
// count is 3 bits, so its range is 0-7
|
||||
// however, it encodes counts 1-8
|
||||
int32_t count = a->count + 1;
|
||||
// todo if cfg.sr = 1
|
||||
if (true) {
|
||||
if (count + a->dest > 15) { // TODO verify against ISA table
|
||||
// invalid
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// TODO cfg.sr = 0
|
||||
}
|
||||
for (int i = 0; i < count; ++i) {
|
||||
// pop regular registers
|
||||
// TODO register pair popping???
|
||||
tcg_gen_qemu_ld_tl(r[a->dest + i], r[CR16C_REGNO_SP], 0, MO_UW);
|
||||
tcg_gen_addi_tl(r[CR16C_REGNO_SP], r[CR16C_REGNO_SP], 2);
|
||||
}
|
||||
// TODO memory spaces(???)
|
||||
// pop RA if requested
|
||||
if (a->ra) {
|
||||
tcg_gen_qemu_ld_tl(r[CR16C_REGNO_RA], r[CR16C_REGNO_SP], 0, MO_32);
|
||||
tcg_gen_addi_tl(r[CR16C_REGNO_SP], r[CR16C_REGNO_SP], 4);
|
||||
}
|
||||
|
||||
if (a->rt) {
|
||||
// basically, JUMP RA
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
|
||||
tcg_gen_goto_tb(0);
|
||||
tcg_gen_mov_i32(pc, r[CR16C_REGNO_RA]);
|
||||
tcg_gen_exit_tb(ctx->base.tb, 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_push(DisasContext *ctx, arg_push *a) {
|
||||
int32_t count = a->count + 1;
|
||||
|
||||
// we need to push the registers in reverse order so that they are in the correct places for POP, e.g.:
|
||||
// SP = 0x100A
|
||||
// # popret $3, R1, RA
|
||||
// 0x1000 R1
|
||||
// 0x1002 R2
|
||||
// 0x1004 R3
|
||||
// 0x1006 RA # 4 bytes!!
|
||||
// 0x100A xxxxx
|
||||
|
||||
// TODO memory spaces
|
||||
// push RA
|
||||
if (a->ra) {
|
||||
tcg_gen_subi_tl(r[CR16C_REGNO_SP], r[CR16C_REGNO_SP], 4);
|
||||
tcg_gen_qemu_st_tl(r[CR16C_REGNO_RA], r[CR16C_REGNO_SP], 0, MO_32);
|
||||
}
|
||||
|
||||
// push regular registers
|
||||
for (int i = count - 1; i >= 0; --i) {
|
||||
// TODO register pairs
|
||||
tcg_gen_subi_tl(r[CR16C_REGNO_SP], r[CR16C_REGNO_SP], 2);
|
||||
tcg_gen_qemu_st_tl(r[a->src + i], r[CR16C_REGNO_SP], 0, MO_16);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Some instructions aren't implemented yet, eg. because of some binutils that make them hard to verify and we'll fix first */
|
||||
static bool trans_UNIMPLEMENTED(DisasContext *ctx, arg_UNIMPLEMENTED *a) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue