It is currently Fri Dec 15, 2017 6:48 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 19 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: Wed Dec 21, 2011 8:35 am 
Offline

Joined: Fri Apr 29, 2011 9:44 pm
Posts: 267
Very awesome! Great job!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 21, 2011 9:38 am 
Offline

Joined: Fri Apr 29, 2011 9:44 pm
Posts: 267
The implementation is very clever. I must study this further.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Dec 21, 2011 9:56 am 
Offline

Joined: Fri Apr 29, 2011 9:44 pm
Posts: 267
How did you generate the Base64 (err, Base256? =D) encoded strings? Another program, or by hand?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 30, 2011 4:34 pm 
Offline
User avatar

Joined: Fri Oct 14, 2011 1:09 am
Posts: 248
Zelex wrote:
How did you generate the Base64 (err, Base256? =D) encoded strings? Another program, or by hand?

Sorry about taking many days to notice your post. phpBB only sent me a notification of your first post, and I did not know about the second one. Or the third one.
Answer: Another program.

For each micro-op (each of those lines is one), a list of opcodes using that micro-op is built.
Code:
  // $point = current micro-op ID, $plans = list of micro-ops required by all opcodes (the list is called a "plan")
  $ops = Array();
  foreach($plans as $op => $plan)
    if(isset($plan[$point]))
      $ops[$op] = $op;
Then the list is converted into a string by translating 8 bits at once using a character lookup array:
Code:
    $ranges = Array();
    for($n=0; $n*8<0x103; ++$n) //
      $ranges[] = 0;
    foreach($ops as $o)
      $ranges[(int)($o / 8)] |= 1 << ($o % 8);
    $s = '';
    for($n=0; $n*8<0x103; ++$n) //
      $s .= $rangebytetranslation[$ranges[$n]];
    $s = '"'.$s.'"';

The lookup array (which determines which character maps into which byte) was built as follows:
Code:
$bitno = 0;
// Initial version, using BASE64 (6 bits per character):
$charset = " !";
 for($c=0; $c<15; ++$c) $charset .= chr(65+$c); // A-O
 for($c=0; $c<11; ++$c) $charset .= chr(80+$c); // P-Z
 for($c=1; $c<10; ++$c) $charset .= chr(48+$c); // 0-9
 for($c=0; $c<15; ++$c) $charset .= chr(97+$c); // a-o
 for($c=0; $c<11; ++$c) $charset .= chr(112+$c); // p-z

// Figure out which kind of bytes we actually are going to need to present:
$rangebytetranslation = Array();
$rangebytes = Array();
foreach($points as $point => $code)
{
  $ops = Array();
  foreach($plans as $op => $plan) if(isset($plan[$point])) $ops[$op] = $op;
  $ranges = Array();
  for($n=0; $n*8<0x103; ++$n) $ranges[] = 0;
  foreach($ops as $o)         $ranges[(int)($o / 8)] |= 1 << ($o % 8);
  foreach($ranges as $v) @$rangebytes[$v] += 1;
}
ksort($rangebytes); #$rangebytes = array_reverse($rangebytes, true);

By observing patterns within the bytes that need to be represented, I created an encoding which is easy to encode and relatively easy to decode.

Code:
// Assign a character for each of those distinct bytes.
$n=94;
$tab = ''; $firstn=-1;
foreach($rangebytes as $v=>$tmp)
{
  if($v<=1) $c = 32+$v;
  #elseif($v <= 26) $c = 64 + $v;
  elseif($v <  64) $c = 40 + $v;
  else { if($firstn<0) $firstn = $v;
         $tab .= chr(32 + $v - $firstn);
         $c = $n++; }//?
  $rangebytetranslation[$v] = chr($c);//$charset[$n++];
}


By the way, here is a version that uses hexadecimal numeric constants, requiring no C++0x. One may guess why I did not use it in that video.
Code:
        /* Decode address operand */
        t(1,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, addr = 0xFFFA) // NMI vector location
        t(2,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, addr = 0xFFFC) // Reset vector location
        t(4,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001, addr = 0xFFFE) // Interrupt vector location
        t(0,0xFAFFF0FA,0xFAFFF0FA,0xFAFFF0FA,0xFAFFF0FA,0xFAFFF0FA,0xFAFFF0FA,0xFAFFF0FB,0xFAFFF0FA, addr = RB(PC++))
        t(0,0xF0F0000A,0xF0F0000A,0x3030000A,0x3030000A,0xF0F0000A,0xF0F0000A,0xF0F0000A,0xF0F0000A, d = X) // register index
        t(0,0x0A0E0000,0x0A0E0000,0xCACE0000,0xCACE0000,0x0A0E0000,0x0A0E0000,0x0A0E0000,0x0A0E0000, d = Y)
        t(0,0x00F0000A,0x00F0000A,0x00F0000A,0x00F0000A,0x00F0000A,0x00F0000A,0x00F0000A,0x00F0000A, addr=u8(addr+d); d=0; tick())              // add zeropage-index
        t(0,0xFA00F000,0xFA00F000,0xFA00F000,0xFA00F000,0xFA00F000,0xFA00F000,0xFA00F001,0xFA00F000, addr=u8(addr);   addr+=256*RB(PC++))       // absolute address
        t(7,0x000E000A,0x000E000A,0x000E000A,0x000E000A,0x000E100A,0x000E000A,0x000E000A,0x000E000B, addr=RB(c=addr); addr+=256*RB(wrap(c,c+1)))// indirect w/ page wrap
        t(0,0x32020000,0x32020000,0xFA0E0000,0x00000000,0x32020000,0x32020000,0x32020000,0x32020000, Misfire(addr, addr+d)) // abs. load: extra misread when cross-page
        t(0,0xC80C0000,0xC80C0000,0x00000000,0xFA0E0000,0xC80C0000,0xC80C0000,0xC80C0000,0xC80C0000, RB(wrap(addr, addr+d)))// abs. store: always issue a misread
        /* Load source operand */
        t(0,0x00000000,0xAAAAAAAA,0x00000500,0xAAAAAAAA,0x00000C04,0xAAAAAFAE,0xAAAABEBE,0xAAAAAEAE, t &= A) // Many operations take A or X as operand. Some try in
        t(0,0x00001111,0x00000C00,0x00000000,0xCCCCCCC8,0x00000000,0x00000000,0x00000000,0x00000000, t &= X) // error to take both; the outcome is an AND operation.
        t(0,0x00000000,0x00001111,0x00000000,0x11101111,0x00000000,0x00000000,0x00000000,0x00000000, t &= Y) // sty,dey,iny,tya,cpy
        t(0,0x00000000,0x00000000,0x0C000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, t &= S) // tsx, las
        t(7,0x01010000,0x01010000,0x01010000,0x00010000,0x01010000,0x01010000,0x01010000,0x01010101, t &= P.raw|pbits; c = t)// php, flag test/set/clear, interrupts
        t(0,0x00001011,0xAAAABABB,0x00000000,0x00000000,0x00000000,0xAAAAA2AA,0xAAAAB2BA,0xAAAAA2AA, c = t; t = 0xFF)        // save as second operand
        t(0,0xEAEEF0FA,0xEAEEF0FA,0xFAFEF0FA,0x00000000,0xEAEEE0EA,0xEAEEE0EA,0xEAEEF0FA,0xEAEEE0EA, t &= RB(addr+d)) // memory operand
        t(0,0x00000A05,0x00000A05,0x00000A05,0x00000A05,0x00000A04,0x00000A04,0x00000A04,0x00000A04, t &= RB(PC++))   // immediate operand
        /* Operations that mogrify memory operands directly */
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00001010,0x00000000, P.V = t & 0x40; P.N = t & 0x80) // bit
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0xC8CCCCCC,0x00000000,0xC8CCC4CC,0x00000000, sb = P.C)       // rol,rla, ror,rra,arr
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000800,0x00000000,0xC8CCCCCC,0xC8CCCCCC, P.C = t & 0x80) // rol,rla, asl,slo,[arr,anc]
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0xC8CCC4CC,0xC8CCCCCC,0x00000000,0x00000000, P.C = t & 0x01) // lsr,sre, ror,rra,asr
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0xC8CCC4CC,0xC8CCC4CC, t = (t << 1) | (sb << 0))
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0xC8CCCCCC,0xC8CCCCCC,0x00000000,0x00000000, t = (t >> 1) | (sb << 7))
        t(0,0x00000000,0xC8CCC4C8,0x00000000,0x00000100,0x00000000,0x00000000,0x00000000,0x00000000, t = u8(t - 1))  // dec,dex,dey,dcp
        t(0,0xC8CCC1C8,0x00000100,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, t = u8(t + 1))  // inc,inx,iny,isb
        /* Store modified value (memory) */
        t(0,0xC8CCC0C8,0xC8CCC0C8,0x00000000,0x22FEF0FA,0xC8CCC0C8,0xC8CCC0C8,0xC8CCC0C8,0xC8CCC0C8, WB(addr+d, t))
        t(0,0x00000000,0x00000000,0x00000000,0xD8000000,0x00000000,0x00000000,0x00000000,0x00000000, WB(wrap(addr, addr+d), t &= ((addr+d) >> 8))) // [shx,shy,shs,sha?]
        /* Some operations used up one clock cycle that we did not account for yet */
        t(7,0xDDDCC5C8,0xDDDCC5C8,0x05000500,0x05000500,0xDDDCC5D9,0xDDDCC5D8,0xDDDCC5C9,0xDDDCD5D9, tick()) // nop,flag ops,inc,dec,shifts,stack,transregister,interrupts
        /* Stack operations and unconditional jumps */
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000100,0x00000001,0x00000100,0x00000000, tick(); t = Pop())                        // pla,plp,rti
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000001,0x00000000,0x00000000, RB(PC++); PC = Pop(); PC |= (Pop() << 8)) // rti,rts
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000000,0x00000000,0x00000000, RB(PC++))  // rts
        t(7,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000001,0x00000001, d=PC+(op?-1:1); Push(d>>8); Push(d))      // jsr, interrupts
        t(7,0x00000000,0x00000000,0x00000000,0x00000000,0x00001000,0x00001000,0x00000001,0x00000001, PC = addr) // jmp, jsr, interrupts
        t(7,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000100,0x00000000,0x00000101, Push(t))   // pha, php, interrupts
        /* Bitmasks */
        t(7,0x01010000,0x01010000,0x01010000,0x00010000,0x01010000,0x01010000,0x01010000,0x01010001, t = 1)
        t(0,0x01010000,0x01010000,0x00000000,0x00000000,0x00000000,0x00000000,0x00010000,0x00010000, t <<= 1)
        t(7,0x01000000,0x01000000,0x01000000,0x00000000,0x01010000,0x01010000,0x00010000,0x00010001, t <<= 2)
        t(0,0x00000000,0x00000000,0x01000000,0x00000000,0x00010000,0x00010000,0x00010000,0x00010000, t <<= 4)
        t(0,0xAAAAAAAA,0x01000000,0x01000000,0x00000000,0x00000000,0x01000000,0x00000000,0x01000000, t = u8(~t)) // sbc, isb,      clear flag
        t(7,0x01000000,0x00000000,0x00000000,0x00000000,0x01000000,0x00000000,0x01000000,0xAAAAA2AB, t = c | t)  // ora, slo,      set flag
        t(0,0x00010000,0x01010000,0x01010000,0x00010000,0x00010000,0x01010000,0xAAABB2BA,0x01010000, t = c & t)  // and, bit, rla, clear/test flag
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0xAAAAA2AA,0x00000000,0x00000000, t = c ^ t)  // eor, sre
        /* Conditional branches */
        t(0,0x00010000,0x00000000,0x00010000,0x00000000,0x00010000,0x00000000,0x00010000,0x00000000, if(t)  { tick(); Misfire(PC, addr = s8(addr) + PC); PC=addr; })
        t(0,0x00000000,0x00010000,0x00000000,0x00010000,0x00000000,0x00010000,0x00000000,0x00010000, if(!t) { tick(); Misfire(PC, addr = s8(addr) + PC); PC=addr; })
        /* Addition and subtraction */
        t(0,0xAAAAAAAA,0x00000000,0x00000000,0x00000000,0xAAAAA2AA,0x00000000,0x00000000,0x00000000, c = t; t += A + P.C; P.V = (c^t) & (A^t) & 0x80; P.C = t & 0x100)
        t(0,0x00001011,0xAAAABABB,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, t = c - t; P.C = ~t & 0x100) // cmp,cpx,cpy, dcp, sbx
        /* Store modified value (register) */
        t(0,0xAAAAAAAA,0x00000000,0xAAAAAAAA,0x01000C00,0xAAAAAFAE,0xAAAAAEAE,0xAAAAAEAE,0xAAAAAEAE, A = t)
        t(0,0x00000100,0x00000C00,0xCCCCCCCC,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, X = t) // ldx, dex, tax, inx, tsx,lax,las,sbx
        t(0,0x00000000,0x00000100,0x10101111,0x00000100,0x00000000,0x00000000,0x00000000,0x00000000, Y = t) // ldy, dey, tay, iny
        t(0,0x00000000,0x00000000,0x08000000,0x0C000000,0x00000000,0x00000000,0x00000000,0x00000000, S = t) // txs, las, shs
        t(7,0x01000000,0x01000000,0x01000000,0x00000000,0x01000000,0x01000001,0x01000100,0x01000001, P.raw = t & ~0x30) // plp, rti, flag set/clear
        /* Generic status flag updates */
        t(0,0xEAEEFBFB,0xEAEEFFFB,0xFEFEFFFF,0x01000D00,0xEAEEEFEE,0xEAEEEEEE,0xEAEEEEEE,0xEAEEEEEE, P.N = t & 0x80)
        t(0,0xEAEEFBFB,0xEAEEFFFB,0xFEFEFFFF,0x01000D00,0xEAEEEFEE,0xEAEEEEEE,0xEAEEFEFE,0xEAEEEEEE, P.Z = u8(t) == 0)
        t(0,0x00000000,0x00000000,0x00000000,0x00000000,0x00000800,0x00000000,0x00000000,0x00000000, P.V = (((t >> 5)+1)&2))         // [arr]
It can be decoded like this:
Code:
        // Define the opcode decoding matrix, which decides which micro-operations constitute
        // any particular opcode. (Note: The PLA of 6502 works on a slightly different principle.)
        const unsigned o8 = op / 32, o8m = 1u << (op%32);
        #define t(w8,w7,w6,w5,w4,w3,w2,w1,w0,code) if( \
                (o8<1?w0##u : o8<2?w1##u  : o8<3?w2##u : o8<4?w3##u : \
                 o8<5?w4##u : o8<6?w5##u  : o8<7?w6##u : o8<8?w7##u : w8##u) & o8m) { code; }


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page Previous  1, 2

All times are UTC - 7 hours


Who is online

Users browsing this forum: Yahoo [Bot] and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group