Note that there are some explanatory texts on larger screens.

plurals
  1. POTrying to understand complicated use of macros, templates and enums in C++11
    text
    copied!<p>I just saw this video <a href="http://www.youtube.com/watch?v=y71lli8MS8s" rel="nofollow">http://www.youtube.com/watch?v=y71lli8MS8s</a> and find it amazing. The question is about his opcode decoding matrix function:</p> <pre><code>template&lt;u16 op&gt; // Execute a single CPU instruction, defined by opcode "op". void Ins() // With template magic, the compiler will literally synthesize &gt;256 different functions. { // Note: op 0x100 means "NMI", 0x101 means "Reset", 0x102 means "IRQ". They are implemented in terms of "BRK". // User is responsible for ensuring that WB() will not store into memory while Reset is being processed. unsigned addr=0, d=0, t=0xFF, c=0, sb=0, pbits = op&lt;0x100 ? 0x30 : 0x20; // 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.) enum { o8 = op/8, o8m = 1 &lt;&lt; (op%8) }; // Fetch op'th item from a bitstring encoded in a data-specific variant of base64, // where each character transmits 8 bits of information rather than 6. // This peculiar encoding was chosen to reduce the source code size. // Enum temporaries are used in order to ensure compile-time evaluation. #define t(s,code) { enum { \ i=o8m &amp; (s[o8]&gt;90 ? (130+" (),-089&lt;&gt;?BCFGHJLSVWZ[^hlmnxy|}"[s[o8]-94]) \ : (s[o8]-" (("[s[o8]/39])) }; if(i) { code; } } /* Decode address operand */ t(" !", addr = 0xFFFA) // NMI vector location t(" *", addr = 0xFFFC) // Reset vector location t("! ,", addr = 0xFFFE) // Interrupt vector location t("zy}z{y}zzy}zzy}zzy}zzy}zzy}zzy}z ", addr = RB(PC++)) t("2 yy2 yy2 yy2 yy2 XX2 XX2 yy2 yy ", d = X) // register index t(" 62 62 62 62 om om 62 62 ", d = Y) t("2 y 2 y 2 y 2 y 2 y 2 y 2 y 2 y ", addr=u8(addr+d); d=0; tick()) // add zeropage-index t(" y z!y z y z y z y z y z y z y z ", addr=u8(addr); addr+=256*RB(PC++)) // absolute address t("3 6 2 6 2 6 286 2 6 2 6 2 6 2 6 /", addr=RB(c=addr); addr+=256*RB(wrap(c,c+1)))// indirect w/ page wrap t(" *Z *Z *Z *Z 6z *Z *Z ", Misfire(addr, addr+d)) // abs. load: extra misread when cross-page t(" 4k 4k 4k 4k 6z 4k 4k ", RB(wrap(addr, addr+d)))// abs. store: always issue a misread /* Load source operand */ t("aa__ff__ab__,4 ____ - ____ ", t &amp;= A) // Many operations take A or X as operand. Some try in t(" knnn 4 99 ", t &amp;= X) // error to take both; the outcome is an AND operation. t(" 9989 99 ", t &amp;= Y) // sty,dey,iny,tya,cpy t(" 4 ", t &amp;= S) // tsx, las t("!!!! !! !! !! ! !! !! !!/", t &amp;= P.raw|pbits; c = t)// php, flag test/set/clear, interrupts t("_^__dc___^__ ed__98 ", c = t; t = 0xFF) // save as second operand t("vuwvzywvvuwvvuwv zy|zzywvzywv ", t &amp;= RB(addr+d)) // memory operand t(",2 ,2 ,2 ,2 -2 -2 -2 -2 ", t &amp;= RB(PC++)) // immediate operand /* Operations that mogrify memory operands directly */ t(" 88 ", P.V = t &amp; 0x40; P.N = t &amp; 0x80) // bit t(" nink nnnk ", sb = P.C) // rol,rla, ror,rra,arr t("nnnknnnk 0 ", P.C = t &amp; 0x80) // rol,rla, asl,slo,[arr,anc] t(" nnnknink ", P.C = t &amp; 0x01) // lsr,sre, ror,rra,asr t("ninknink ", t = (t &lt;&lt; 1) | (sb * 0x01)) t(" nnnknnnk ", t = (t &gt;&gt; 1) | (sb * 0x80)) t(" ! kink ", t = u8(t - 1)) // dec,dex,dey,dcp t(" ! khnk ", t = u8(t + 1)) // inc,inx,iny,isb /* Store modified value (memory) */ t("kgnkkgnkkgnkkgnkzy|J kgnkkgnk ", WB(addr+d, t)) t(" q ", WB(wrap(addr, addr+d), t &amp;= ((addr+d) &gt;&gt; 8))) // [shx,shy,shs,sha?] /* Some operations used up one clock cycle that we did not account for yet */ t("rpstljstqjstrjst - - - -kjstkjst/", tick()) // nop,flag ops,inc,dec,shifts,stack,transregister,interrupts /* Stack operations and unconditional jumps */ t(" ! ! ! ", tick(); t = Pop()) // pla,plp,rti t(" ! ! ", RB(PC++); PC = Pop(); PC |= (Pop() &lt;&lt; 8)) // rti,rts t(" ! ", RB(PC++)) // rts t("! ! /", d=PC+(op?-1:1); Push(d&gt;&gt;8); Push(d)) // jsr, interrupts t("! ! 8 8 /", PC = addr) // jmp, jsr, interrupts t("!! ! /", Push(t)) // pha, php, interrupts /* Bitmasks */ t("! !! !! !! !! ! !! !! !!/", t = 1) t(" ! ! !! !! ", t &lt;&lt;= 1) t("! ! ! !! !! ! ! !/", t &lt;&lt;= 2) t(" ! ! ! ! ! ", t &lt;&lt;= 4) t(" ! ! ! !____ ", t = u8(~t)) // sbc, isb, clear flag t("`^__ ! ! !/", t = c | t) // ora, slo, set flag t(" !!dc`_ !! ! ! !! !! ! ", t = c &amp; t) // and, bit, rla, clear/test flag t(" _^__ ", t = c ^ t) // eor, sre /* Conditional branches */ t(" ! ! ! ! ", if(t) { tick(); Misfire(PC, addr = s8(addr) + PC); PC=addr; }) t(" ! ! ! ! ", if(!t) { tick(); Misfire(PC, addr = s8(addr) + PC); PC=addr; }) /* Addition and subtraction */ t(" _^__ ____ ", c = t; t += A + P.C; P.V = (c^t) &amp; (A^t) &amp; 0x80; P.C = t &amp; 0x100) t(" ed__98 ", t = c - t; P.C = ~t &amp; 0x100) // cmp,cpx,cpy, dcp, sbx /* Store modified value (register) */ t("aa__aa__aa__ab__ 4 !____ ____ ", A = t) t(" nnnn 4 ! ", X = t) // ldx, dex, tax, inx, tsx,lax,las,sbx t(" ! 9988 ! ", Y = t) // ldy, dey, tay, iny t(" 4 0 ", S = t) // txs, las, shs t("! ! ! !! ! ! ! ! !/", P.raw = t &amp; ~0x30) // plp, rti, flag set/clear /* Generic status flag updates */ t("wwwvwwwvwwwvwxwv 5 !}}||{}wv{{wv ", P.N = t &amp; 0x80) t("wwwv||wvwwwvwxwv 5 !}}||{}wv{{wv ", P.Z = u8(t) == 0) t(" 0 ", P.V = (((t &gt;&gt; 5)+1)&amp;2)) // [arr] /* All implemented opcodes are cycle-accurate and memory-access-accurate. * [] means that this particular separate rule exists only to provide the indicated unofficial opcode(s). */ } </code></pre> <p>What I find very confusing is the define statement. When macros get expanded it looks like this <a href="http://codepad.org/bUxdX8MQ" rel="nofollow">http://codepad.org/bUxdX8MQ</a>. But how can <code>'130+" (),-089&lt;&gt;?BCFGHJLSVWZ[^hlmnxy|}"'</code> be legal C++ code? As far as I know combining strings and integers in such fashion is illegal. Also this <code>("zy}z{y}zzy}zzy}zzy}zzy}zzy}zzy}z "[o8]&gt;90)</code> does not make sense at all, unless C++11 added support to access string characters in an array fashion. Hoping to learn something new!</p> <p>EDIT: Thank you to everyone who responded. I was unaware that <code>"blabla"[idx]</code> was allowed in C/C++ now that I do the code makes sense.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload