Currently all architecures have there own core.jit. These are very
similar, e.g. checking for MAPped registers, but differ depending on
the processor architecure: basically we have 3 register machines
(alpha, arm, ppc, sparc) and a 2 register machine (i386).

My proposal is to write a universal core.jit, which provides the basic
functionality.

e.g.

Parrot_add_i_i_i {
    if (MAP[1] && MAP[2] && MAP[3]) {
#ifdef jit_emit_add_rrr_i	/* 3 reg machine */
	jit_emit_add_rrr_i(MAP(2), MAP(3), MAP(1));
#else
	jit_emit_mov_rr_i(MAP(2), MAP(1));
	jit_emit_add_rr_i(MAP(3), MAP(1));
#endif
    }
    ...

The implementation of these jit_emit_ops would stay in jit_emit.h.

Proposed naming of ops:

  jit_emit_<op>_<rmi>_<in>(...)

  <op> operations mov, add, sub, mul, ...
  <rmi> register, memory, immediate, for all parameters
       (source, dest) or (source, source, dest)
  <in>  integer (or pointer...) or number

  jit_emit_mov_rm_n(<reg>, <mem>)
    (store processor reg to parrot num_reg at mem)
  jit_emit_mov_mr_i(<mem>, <reg>)
    (load processor reg from parrot int_reg at mem)

  The <reg>s would be taken from a list of processor regs, either the
  MAPed ones, or 1 or 2 scratch registers, depending on architecture.


  jit_emit_jmp_p(<cond>, offset)
  jit_emit_call_p(offset)

  Jump to or call parrot funcs at offset.
  <cond> : cond_always, cond_lt,le,gt,ge,eq,ne

  jit_emit_push_<rm>(.., &SP_diff)
  jit_emit_call_c(addr)
  jit_emit_call_vtable(mem_of_pmc_reg, int n)
  jit_emit_add_SP(SP_diff)
  jit_emit_ret

  Push (or whatever) params on stack, preparing for a native call,
  correct SP after return.


With these ops, all the current functionality could be in one file,
all the register mapping would be centralized.
If something doesn't fit, it could be undefined for this architecture,
the implementation would then be in jit_emit.h.

Comments welcome
leo

Reply via email to