On Thu, Feb 14, 2013 at 6:19 PM, Richard Henderson <r...@twiddle.net> wrote: > On 02/13/2013 02:26 PM, Anthony Green wrote: >> + case 0x03: /* jsra */ >> + { >> + /* Load the stack pointer into T0. */ >> + TCGv t1 = new_tmp(); >> + TCGv t2 = new_tmp(); >> + >> + tcg_gen_movi_i32(t1, ctx->pc+6); >> + >> + /* Make space for the static chain and return address. */ >> + tcg_gen_subi_i32(t2, REG(1), 8); >> + tcg_gen_mov_i32(REG(1), t2); >> + tcg_gen_qemu_st32(t1, REG(1), ctx->memidx); >> + >> + /* Push the current frame pointer. */ >> + tcg_gen_subi_i32(t2, REG(1), 4); >> + tcg_gen_mov_i32(REG(1), t2); >> + tcg_gen_qemu_st32(REG(0), REG(1), ctx->memidx); > > There are two exceptions that can be taken here, for the two stores. > Are you certain that REG(1) should be updated before both are handled? > Should the write to REG(1) be delayed until after the second store?
You raise a good point, but that's approximately how the hardware works today. We write to $sp midway through the multi-cycle jsr instruction (before the second write). https://github.com/atgreen/moxie-cores/blob/master/cores/MoxieLite/moxielite.vhd#L932 Something to put on the TODO list for both hw and qemu. >> + case 0x04: /* ret */ >> + { >> + TCGv t1 = new_tmp(); >> + >> + /* The new $sp is the old $fp. */ >> + tcg_gen_mov_i32(REG(1), REG(0)); >> + >> + /* Pop the frame pointer. */ >> + tcg_gen_qemu_ld32u(REG(0), REG(1), ctx->memidx); >> + tcg_gen_addi_i32(t1, REG(1), 4); >> + tcg_gen_mov_i32(REG(1), t1); >> + >> + >> + /* Pop the return address and skip over the static chain >> + slot. */ >> + tcg_gen_qemu_ld32u(cpu_pc, REG(1), ctx->memidx); >> + tcg_gen_addi_i32(t1, REG(1), 8); >> + tcg_gen_mov_i32(REG(1), t1); > > Similarly, should any global variable be updated before the second load? > Same comments apply to JSR and SWI. Same answer applies. Thanks, AG