lxa now works, I hope; traps are better (and stubbed out on qemuppc).

This commit is contained in:
David Given 2016-11-20 11:57:21 +01:00
parent d5328492d7
commit 196fa914b3
2 changed files with 39 additions and 56 deletions

View file

@ -7,6 +7,7 @@ static struct ir* stack[64];
static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode); static struct ir* convert(struct ir* src, int srcsize, int destsize, int opcode);
static struct ir* appendir(struct ir* ir); static struct ir* appendir(struct ir* ir);
static void insn_ivalue(int opcode, arith value);
static void reset_stack(void) static void reset_stack(void)
{ {
@ -486,7 +487,12 @@ static void insn_simple(int opcode)
case op_trp: helper_function(".trp"); break; case op_trp: helper_function(".trp"); break;
case op_sig: helper_function(".sig"); break; case op_sig: helper_function(".sig"); break;
case op_rtt: helper_function(".rtt"); break;
case op_rtt:
{
insn_ivalue(op_ret, 0);
break;
}
/* FIXME: These instructions are really complex and barely used /* FIXME: These instructions are really complex and barely used
* (Modula-2 bitset support, I believe). Leave them until later. */ * (Modula-2 bitset support, I believe). Leave them until later. */
@ -1202,11 +1208,26 @@ static void insn_ivalue(int opcode, arith value)
case op_lxa: case op_lxa:
{ {
/* What does this actually *do*? The spec doesn't say. */ struct ir* ir;
appendir(
/* Walk the static chain. */
ir = new_ir0(
IR_GETFP, EM_pointersize
);
while (value--)
{
ir = new_ir1(
IR_CHAINFP, EM_pointersize,
ir
);
}
push(
new_ir1( new_ir1(
IR_CALL, 0, IR_FPTOAB, EM_pointersize,
new_labelir(".unimplemented_lxa") ir
) )
); );
break; break;

View file

@ -46,60 +46,22 @@ EBADLIN = 26
EBADGTO = 27 EBADGTO = 27
EUNIMPL = 63 ! unimplemented em-instruction called EUNIMPL = 63 ! unimplemented em-instruction called
! EM trap handling.
.define .trap_ecase .define .trap_ecase
.trap_ecase: .trap_ecase:
addi r3, r0, ECASE b .trp
b .trap
.define .trap_earray .define .trap_earray
.trap_earray: .trap_earray:
addi r3, r0, EARRAY b .trp
b .trap
.define .trp
.define .trap .trp:
.trap: b .trp ! spin forever
cmpi cr0, 0, r3, 15 ! traps >15 can't be ignored
bc IFTRUE, LT, 1f .define .sig
.sig:
addi r4, r0, 1 lwz r3, 0(sp)
rlwnm r4, r4, r3, 0, 31 ! calculate trap bit
li32 r5, .ignmask
lwz r5, 0(r5) ! load ignore mask
and. r4, r4, r5 ! compare
bclr IFFALSE, EQ, 0 ! return if non-zero
1:
li32 r4, .trppc li32 r4, .trppc
lwz r5, 0(r4) ! load user trap routine stw r3, 0(r4)
or. r5, r5, r5 ! test bclr ALWAYS, 0, 0 ! return
bc IFTRUE, EQ, fatal ! if no user trap routine, bail out
addi r0, r0, 0
stw r0, 0(r4) ! reset trap routine
mfspr r0, lr
stwu r0, -4(sp) ! save old lr
stwu r3, -4(sp)
mtspr ctr, r5
bcctrl ALWAYS, 0, 0 ! call trap routine
lwz r0, 4(sp) ! load old lr again
addi sp, sp, 8 ! retract over stack usage
bclr ALWAYS, 0, 0 ! return
fatal:
addi r3, r0, 1
li32 r4, message
addi r5, r0, 6
addi r0, r0, 4 ! write()
sc 0
addi r0, r0, 1 ! exit()
sc 0
.sect .rom
message:
.ascii "TRAP!\n"