Sunday, August 24, 2014

Hey, check it out. I got correct code finally:

Input C code:

unsigned char Round;
#define VDPWD *((volatile char*)0x8C00)
void modulo()
{
  VDPWD = '0' + Round % 10;
}

Output assembly:

modulo:
        movb @Round, r1
        srl  r1, 8
        mov  r1, r2
        clr  r1
        li   r3, >A        div  r3, r1
        mov  r2, r1
        swpb r1  # instruction is right where it's supposed to be
        ai   r1, >3000
        movb r1, @>8C00
        b    *r11

OK, I'll admit it. At first that doesn't seem too exciting. The thing is that I've been looking for a way to cleanly handle this case for a long, long time. I walked away in frustration because I got stuck on this problem. I just need to test this a bit more and we can call this done.

I was looking through older development notes to see if there was anything else left semi-implemented. I found a note to see if there can be any way to remove two jumps in sequence like jlt/jmp

Here are all the conditional jumps and the logic they use:

Conditional flags:
  L - Logical greater than
  A - Arithmetic greater than
  Q - equal

Arithmetic:
<   ~A & ~Q  jlt
>    A & ~Q  jgt
==   Q       jeq
>=   A | Q   jgt,jeq  \__ Ick, go away.
<=  ~A | Q   jlt,jeq  /
!=  ~Q       jne

Logical:
<   ~L & ~Q  jl
>    L & ~Q  jh
==   Q       jeq
>=   L | Q   jhe
<=  ~L | Q   jle
!=  ~Q       jne

Unfortunately, there is no way to completely implement >= and <= in one instruction for all valid imputs, but if the range of the test values were known, we could occasionally replace the jgt,jeq sequence with single jhe instruction.

EX: For byte compares, if A=[0..127] and B=[0..127], then these sequences are equivalent:

jlt ADDR  --> jle ADDR
jeq ADDR

jgt ADDR  --> jhe ADDR
jeq ADDR

Unfortunately, here is no way for the compiler to recognize this situation. If the user knows that their range matches this, they can take advantage of the slightly faster code by doing an unsigned compare. Something like this works:

int fast_lt_eq(int a, int b)
{
  return ((unsigned int)a <= (unsigned int)b);
}

What else...

Way back in June, TheMole on Atariage reported that they were unable to compile a function whose return value was assigned in an asm block and implicitly typecast as the retun value. No problems now.

So at this point, I think I'm up to date on error reports. These are the last items before I move on to new stuff:

1) Test 32-bit shift by variable, I'm not sure I checked that
2) Test assembler for Editor/Assembler adherance for caps and digits for registers, comments, register defines, etc.
3) Check signed vs. unsigned division and multiplication

No comments:

Post a Comment