Wednesday 22 April 2015

Project Wrap up

Project Switch
Project Wrap up
Concluding the final project for spo600 at Seneca College

Sljit

My last post gave a outline of what I was going to try to accomplish but unfortunately I did not get very far. There are many things dealing with this area that I believe would require a greater knowledge of the sljit compiler as a whole. Here is what I have done up to today, It's not much, but it's something.

The defines

For defining the number of float registers for ARM and x86 it should be pretty simple and similar to what he has currently. It could be implemented if unlike me you had a better understanding of saved float registers. Here is what it should look like:
#if (defined SLJIT_CONFIG_ARM_64 && SLJIT_CONFIG_ARM_64)
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 32
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS XX

#elif (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64)
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 8
#if (defined _WIN64)
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS 1
#else
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS XX

#else
#define SLJIT_NUMBER_OF_FLOAT_REGISTERS 6
#define SLJIT_NUMBER_OF_SAVED_FLOAT_REGISTERS XX
(XX should be replaced with correct number)
Defined in the arm documents here is where I found the information for number of floating point registers, It states there is 32 registers for single precision floating point, which are also used as 16 registers for double precision floating point, so I am not sure whether it would be 16 or 32. For x86 I was confused regarding the number of floating point registers used. For example this site has a picture showing 8 registers for floating points, but the title of this page is legacy registers which may mean they are no longer used. In the Intel documentation on page 183 (8.1.2) it states there are 8 in the x87 fpu stack, this made me wonder if these are the legacy registers the other site mentions or if these add on to the legacy registers making it 16 in total. Also in X86 there are Vector floating point registers and from this page I am not sure how many(possibly 16) or if they even come into play in sljit.

Function entry and exit points

Here is the current code in sljit for the entry:
SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compiler,
 sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds,
 sljit_si fscratches, sljit_si fsaveds, sljit_si local_size)
{
 sljit_si i, tmp, offs, prev, saved_regs_size;

 CHECK_ERROR();
 CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size));
 set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size);

 saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0);
 local_size += saved_regs_size + SLJIT_LOCALS_OFFSET;
 local_size = (local_size + 15) & ~0xf;
 compiler->local_size = local_size;

 if (local_size <= (63 * sizeof(sljit_sw))) {
  FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
   | RN(TMP_SP) | ((-(local_size >> 3) & 0x7f) << 15)));
  FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
  offs = (local_size - saved_regs_size) << (15 - 3);
 } else {
  compiler->local_size += 2 * sizeof(sljit_sw);
  local_size -= saved_regs_size;
  saved_regs_size += 2 * sizeof(sljit_sw);
  FAIL_IF(push_inst(compiler, STP_PRE | 29 | RT2(TMP_LR)
   | RN(TMP_SP) | ((-(saved_regs_size >> 3) & 0x7f) << 15)));
  offs = 2 << 15;
 }

 tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG;
 prev = -1;
 for (i = SLJIT_S0; i >= tmp; i--) {
  if (prev == -1) {
   prev = i;
   continue;
  }
  FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
  offs += 2 << 15;
  prev = -1;
 }

 for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) {
  if (prev == -1) {
   prev = i;
   continue;
  }
  FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs));
  offs += 2 << 15;
  prev = -1;
 }

 if (prev != -1)
  FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5)));

 if (compiler->local_size > (63 * sizeof(sljit_sw))) {
  /* The local_size is already adjusted by the saved registers. */
  if (local_size > 0xfff) {
   FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | ((local_size >> 12) << 10) | (1 << 22)));
   local_size &= 0xfff;
  }
  if (local_size)
   FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (local_size << 10)));
  FAIL_IF(push_inst(compiler, ADDI | RD(SLJIT_SP) | RN(TMP_SP) | (0 << 10)));
 }

 if (args >= 1)
  FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S0) | RN(TMP_ZERO) | RM(SLJIT_R0)));
 if (args >= 2)
  FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S1) | RN(TMP_ZERO) | RM(SLJIT_R1)));
 if (args >= 3)
  FAIL_IF(push_inst(compiler, ORR | RD(SLJIT_S2) | RN(TMP_ZERO) | RM(SLJIT_R2)));

 return SLJIT_SUCCESS;
}
I will be honest, I have no idea how this is doing what it is doing(saving registers). I could not code how to extend this to make it save floating point registers, but I can only theorize it has something to do with fscratches and fsaved parameters, that currently are unused within the function. Possibly creating code similar to what is there, for example this line
saved_regs_size = GET_SAVED_REGISTERS_SIZE(scratches, saveds, 0);
Could be replicated to function with floating point registers like this:
fsaved_regs_size = GET_SAVED_FLOAT_REGISTERS_SIZE(fscratches, fsaveds, 0);
But that is all in theory, I am afraid I do not know, or even know how to know, how to do these things in practice.

Register mapping

I did not really get to this part because it seems simple but I have trouble understanding how he chooses the map for the register. For the integer registers of ARM64 this is his register map:
static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 8] = {
  31, 0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 8, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 29, 9, 10, 11, 30, 31
};
I just don't know how he came up with these numbers and also why 8 is added to the size of the register map.

Conclusions

In this post, there was definitely a phrase that came up a lot, it was "I don't know", I think simply after finally finding something to work on, it was just out of my range to complete, even though I am sure it would be an easy task for someone who is experienced in this kind of environment. I think I should have kept my options open and perhaps choose a easier project to work on. I am disappointed in myself for not producing anything worthy of a patch but I am out of time to contribute anything more, In the summer I will try to complete it for fun and will post results if I get anywhere. Regardless of my results I have learned a lot through this project and through this whole course and I think it is always worth challenging yourself to expand your knowledge of computers since there is so much to learn.
Thanks for reading, have a good summer.

No comments:

Post a Comment