It is currently Wed Oct 18, 2017 6:40 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 11 posts ] 
Author Message
PostPosted: Sun Dec 11, 2011 12:33 am 
Offline

Joined: Sun Aug 09, 2009 7:46 am
Posts: 24
I'm curious as to the nature of why certain instructions get certain opcodes, and I predict that they're not all arbitrary. I always wondered if you can determine the address mode used just by looking at the opcode. I have no idea what this area of cpu design is(opcode design?), so it's hard for me to search up on something like this. Also, I'm not sure if this info is even useful, it's only just to satisfy my curiosity of how exactly CPUs work.

I think I've already figured out some address modes.

Like for example, all absolute opcodes:

The low 4 bits of the opcode are either 0x0C, 0x0D or 0x0E
AND
The high 4 bits are zero or a multiple of 2

Any byte that doesn't fall under those criteria but is not listed, such as opcode $0C, is probably an unofficial opcode(but still absolute)

So going by this observation, all of these opcodes must fit my criteria:

Code:
$0C   TOP (NOP) [SKW] (UNOFFICIAL)
$0D   ORA   
$0E   ASL   
$20   JSR  (ANOMALY, neither C, D or E) 
$2C   BIT   
$2D   AND
$2E   ROL
$4C   JMP
$4D   EOR 
$4E   LSR 
$6C   JMP  (ANOMALY, it's Indirect)
$6D   ADC   
$6E   ROR
$8C   STY
$8D   STA
$8E   STX
$AC   LDY
$AD   LDA   
$AE   LDX
$CC   CPY
$CD   CMP
$CE   DEC   
$EC   CPX
$ED   SBC
$EE   INC


I notice how the anomalies are jump type instructions. Just gotta figure out why.

I've also kind of figured out Relative mode (low: zeros, high: one, and multiples of 2 +1). Indirect X looks pretty straight forward too. But some others have me scratching my head, like Implied opcodes.

I'm still kind of looking into this to see if there's a definite pattern. If there's someone here that knows about this kind of thing, wants to help figure this out, or knows where a .txt document on this is at, please tell me!


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 1:40 am 
Offline
User avatar

Joined: Mon Sep 27, 2004 2:13 pm
Posts: 1667
Location: .ma.us
http://www.llx.com/~nparker/a2/opcodes.html


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 1:46 am 
Offline
User avatar

Joined: Mon Apr 04, 2011 11:49 am
Posts: 1905
Location: WhereverIparkIt, USA
Well you've got the right idea. CPUs are set up to decode the opcode and then determine the addressing mode based on the opcode. I haven't looked into the specifics of the 6502 but there is definitely a pattern based on the addressing mode and related opcodes.

As for the Jump, that is generally a special case opcode unlike others. Because it doesn't take any arguments just "jump to this address." And in order to allow for jumps to a wider range of address the opcode is smaller than most allowing for more space for the address.

Not sure if what I'm saying helps, like I said I don't know 6502 specifics. But from what I know about MIPS, ARM, and AVR cpu structure your on the right track. I don't know if there is much documentation on this for 6502, if you can't find much or don't get your answers here you might be better to learn the structure of something more heavily documented for education like MIPS then you could more easily understand why things are done in a certain manner and apply that to the 6502.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 2:30 am 
Offline

Joined: Sun Aug 09, 2009 7:46 am
Posts: 24
kyuusaku wrote:
http://www.llx.com/~nparker/a2/opcodes.html


PERFECT! I don't want to reinvent the wheel, so I'll just soak that page in.

I'm curious how you found that. This subject is probably too obscure to find even with google.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 6:09 am 
Offline
Formerly Fx3
User avatar

Joined: Fri Nov 12, 2004 4:59 pm
Posts: 3064
Location: Brazil
It's really great. However, how would you handle the exceptions? Would you put an "if()" statement at each instruction fetch? That's my doubt.

_________________
Zepper
RockNES developer


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 7:02 am 
Offline
User avatar

Joined: Mon Apr 04, 2011 11:49 am
Posts: 1905
Location: WhereverIparkIt, USA
Zepper wrote:
It's really great. However, how would you handle the exceptions? Would you put an "if()" statement at each instruction fetch? That's my doubt.


I'm not sure if I understand what your asking in reguards to an exception. But if I get the question the answer is that there is priority. ie check these two bits first if they are 00 then go check these bytes to find out what to do. if those two bits were 01 then you should have checked a different set of bytes to determine what to do.

I guess you could think of it as an "if()" because that's what the control unit is doing with every single instruction that comes though. If this opcode do this, if a different opcode do something different etc. It's just doing it with hardware using gates vice a software programming "if()" as it sounds like your implying.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 3:38 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
Undubbed wrote:
kyuusaku wrote:
http://www.llx.com/~nparker/a2/opcodes.html


PERFECT! I don't want to reinvent the wheel, so I'll just soak that page in.

I'm curious how you found that. This subject is probably too obscure to find even with google.


no, when i started writing my 6502 core i did a google search for "6502 instruction encoding" and that was one of the first three or four pages in the results.


Last edited by miker00lz on Sun Dec 11, 2011 3:45 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 3:42 pm 
Offline
User avatar

Joined: Thu Sep 23, 2010 7:28 pm
Posts: 232
infiniteneslives wrote:
Zepper wrote:
It's really great. However, how would you handle the exceptions? Would you put an "if()" statement at each instruction fetch? That's my doubt.


I'm not sure if I understand what your asking in reguards to an exception. But if I get the question the answer is that there is priority. ie check these two bits first if they are 00 then go check these bytes to find out what to do. if those two bits were 01 then you should have checked a different set of bytes to determine what to do.

I guess you could think of it as an "if()" because that's what the control unit is doing with every single instruction that comes though. If this opcode do this, if a different opcode do something different etc. It's just doing it with hardware using gates vice a software programming "if()" as it sounds like your implying.


there are several opcodes that follow no pattern whatsoever. you should have a string of if/elses or a switch block before anything else to find these. if they aren't one of the exceptions to the encoding patterns, then continue parsing based on the regular opcode bitfields.

this is originally how a wrote a 6502 emu, but later changed it to using a function jump table for opcodes/addressing modes because it's slightly easier to maintain, and more readable. i think so, anyway.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Dec 11, 2011 6:55 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19098
Location: NE Indiana, USA (NTSC)
Unless you generate your big jump table the way Bisqwit's sub-1000-line emulator written in C++11 does.

This opcode matrix, widened to 32 instructions per row and with the columns shuffled, might help show the patterns in the 6502 opcodes. Maximize your browser, and if that's not enough, copy this table into a text editor, set the font size down, and maximize that.
Code:
   +00 +04 +08 +0c +10 +14 +18 +1c +01   +05 +09 +0d +11   +15 +19 +1d +02 +06 +0a +0e +12 +16 +1a +1e +03   +07 +0b +0f +13   +17 +1b +1f
00 BRK NOP PHP NOP BPL NOP CLC NOP ORA   ORA ORA ORA ORA   ORA ORA ORA KIL ASL ASL ASL KIL ASL NOP ASL SLO   SLO ANC SLO SLO   SLO SLO SLO
       d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x     d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x
20 JSR BIT PLP BIT BMI NOP SEC NOP AND   AND AND AND AND   AND AND AND KIL ROL ROL ROL KIL ROL NOP ROL RLA   RLA ANC RLA RLA   RLA RLA RLA
   a   d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x     d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x
40 RTI NOP PHA JMP BVC NOP CLI NOP EOR   EOR EOR EOR EOR   EOR EOR EOR KIL LSR LSR LSR KIL LSR NOP LSR SRE   SRE ALR SRE SRE   SRE SRE SRE
       d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x     d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x
60 RTS NOP PLA JMP BVS NOP SEI NOP ADC   ADC ADC ADC ADC   ADC ADC ADC KIL ROR ROR ROR KIL ROR NOP ROR RRA   RRA ARR RRA RRA   RRA RRA RRA
       d       (a) *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x     d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x
80 NOP STY DEY STY BCC STY TYA SHY STA   STA NOP STA STA   STA STA STA NOP STX TXA STX KIL STX TXS SHX SAX   SAX XAA SAX AHX   SAX TAS AHX
   #i  d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x #i  d       a       d,y     a,y (d,x) d   #i  a   (d),y d,y a,y a,y
a0 LDY LDY TAY LDY BCS LDY CLV LDY LDA   LDA LDA LDA LDA   LDA LDA LDA LDX LDX TAX LDX KIL LDX TSX LDX LAX   LAX LAX LAX LAX   LAX LAS LAX
   #i  d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x #i  d       a       d,y     a,y (d,x) d   #i  a   (d),y d,y a,y a,y
c0 CPY CPY INY CPY BNE NOP CLD NOP CMP   CMP CMP CMP CMP   CMP CMP CMP NOP DEC DEX DEC KIL DEC NOP DEC DCP   DCP AXS DCP DCP   DCP DCP DCP
   #i  d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x #i  d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x
e0 CPX CPX INX CPX BEQ NOP SED NOP SBC   SBC SBC SBC SBC   SBC SBC SBC NOP INC NOP INC KIL INC NOP INC ISC   ISC SBC ISC ISC   ISC ISC ISC
   #i  d       a   *+d d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x #i  d       a       d,x     a,x (d,x) d   #i  a   (d),y d,x a,y a,x


Top
 Profile  
 
 Post subject:
PostPosted: Mon Dec 12, 2011 12:22 pm 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6277
Location: Seattle
Also see the similar rearrangement I did here.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Dec 30, 2011 5:03 pm 
Offline
User avatar

Joined: Fri Oct 14, 2011 1:09 am
Posts: 248
This is the table of opcodes that I used for creating the micro-op data for my emulator. It contains all opcodes supported by it, grouped by the mnemonic. (The combination of mnemonic and the addressing mode is used to select the list of micro-ops for the opcode.)
I have intentionally laid out the table in a manner that emphasizes regular patterns within the opcode numbers.

Note that I changed some NOP/DOP/TOP opcodes into actual work-bearing opcodes (such as "STY imm" (80)), simply by following the pattern of existing opcodes. Of course, "STY imm" accomplishes nothing, hence it is considered a NOP opcode (in a similar manner as "XCHG AX, AX" is dubbed "NOP" in the x86 platform).
I also incorporated the JAM/KIL opcodes into the matrix, so e.g. "ASL imm" (02) does something nonsensical rather than jamming the emulator.

Code:
  // 0,4,8,C
  //              Imm   Zpg   ZpxY  IndY  AbsX
  //           ..    Rel   ZpgX  IndX  Abs   AbsY
  set( "bit", "--'--'--'24'--'--'--'--'2C'--'--'--" ); // 20 = jsr, 28=plp
  set( "nop", "--'--'--'44'54'--'--'--'--'--'--'--" ); // 4C = jmp, 40=rti, 48=pha
  set( "nop", "--'--'--'64'74'--'--'--'--'--'--'--" );
  set( "sty", "--'80'--'84'94'--'--'--'8C'--'--'--" ); // 80=DOP
  set( "ldy", "--'A0'--'A4'B4'--'--'--'AC'BC'--'--" ); // A8=tay
  set( "cpy", "--'C0'--'C4'--'--'--'--'CC'--'--'--" ); // C8=iny
  set( "cpx", "--'E0'--'E4'--'--'--'--'EC'--'--'--" ); // E8=inx
  set( "nop", "--'--'--'04'14'--'--'--'0C'1C'--'--" ); // 0C=TOP, 1C = TOP
  set( "nop", "--'--'--'--'34'--'--'--'--'3C'--'--" ); // 34=DOP, 3C = TOP
  set( "nop", "--'--'--'--'--'--'--'--'--'5C'--'--" ); //         5C = TOP
  set( "nop", "--'--'--'--'--'--'--'--'--'7C'--'--" ); //         7C = TOP
  set( "nop", "--'--'--'--'D4'--'--'--'--'DC'--'--" ); // D4=DOP, DC = TOP
  set( "nop", "--'--'--'--'F4'--'--'--'--'FC'--'--" ); // F4=DOP, FC = TOP

  set( "brk", "00'--'--'--'--'--'--'--'--'--'--'--" );
  set( "jsr", "--'--'--'--'--'--'--'--'20'--'--'--" );
  set( "rti", "40'--'--'--'--'--'--'--'--'--'--'--" );
  set( "rts", "60'--'--'--'--'--'--'--'--'--'--'--" ); 

  set( "bpl", "--'--'10'--'--'--'--'--'--'--'--'--" );
  set( "bmi", "--'--'30'--'--'--'--'--'--'--'--'--" );
  set( "bvc", "--'--'50'--'--'--'--'--'--'--'--'--" );
  set( "bvs", "--'--'70'--'--'--'--'--'--'--'--'--" );
  set( "bcc", "--'--'90'--'--'--'--'--'--'--'--'--" );
  set( "bcs", "--'--'B0'--'--'--'--'--'--'--'--'--" );
  set( "bne", "--'--'D0'--'--'--'--'--'--'--'--'--" );
  set( "beq", "--'--'F0'--'--'--'--'--'--'--'--'--" );

  set( "php", "08'--'--'--'--'--'--'--'--'--'--'--" );
  set( "plp", "28'--'--'--'--'--'--'--'--'--'--'--" );
  set( "pha", "48'--'--'--'--'--'--'--'--'--'--'--" );
  set( "pla", "68'--'--'--'--'--'--'--'--'--'--'--" );
  set( "dey", "88'--'--'--'--'--'--'--'--'--'--'--" );
  set( "tay", "A8'--'--'--'--'--'--'--'--'--'--'--" );
  set( "iny", "C8'--'--'--'--'--'--'--'--'--'--'--" );
  set( "inx", "E8'--'--'--'--'--'--'--'--'--'--'--" );

  set( "clc", "18'--'--'--'--'--'--'--'--'--'--'--" ); // 1 : 0001
  set( "sec", "38'--'--'--'--'--'--'--'--'--'--'--" ); // 1 : 0011
  set( "cli", "58'--'--'--'--'--'--'--'--'--'--'--" ); // 4 : 0101
  set( "sei", "78'--'--'--'--'--'--'--'--'--'--'--" ); // 4 : 0111
  set( "clv", "B8'--'--'--'--'--'--'--'--'--'--'--" ); // 64: 1011
  set( "cld", "D8'--'--'--'--'--'--'--'--'--'--'--" ); // 8 : 1101
  set( "sed", "F8'--'--'--'--'--'--'--'--'--'--'--" ); // 8 : 1111

  set( "tya", "98'--'--'--'--'--'--'--'--'--'--'--" );

  set( "jmp", "--'--'--'--'--'--'--'--'4C'--'--'6C" );
  // 1,5,9,D
  set( "ora", "--'09'--'05'15'--'01'11'0D'1D'19'--" );
  set( "and", "--'29'--'25'35'--'21'31'2D'3D'39'--" ); 
  set( "eor", "--'49'--'45'55'--'41'51'4D'5D'59'--" );
  set( "adc", "--'69'--'65'75'--'61'71'6D'7D'79'--" );
  set( "sta", "--'89'--'85'95'--'81'91'8D'9D'99'--" ); // 89=DOP
  set( "lda", "--'A9'--'A5'B5'--'A1'B1'AD'BD'B9'--" );
  set( "cmp", "--'C9'--'C5'D5'--'C1'D1'CD'DD'D9'--" );
  set( "sbc", "--'E9'--'E5'F5'--'E1'F1'ED'FD'F9'--" ); 

  // 2,6,A,E
  set( "asl", "0A'02'--'06'16'--'--'12'0E'1E'--'--" ); // 02=JAM, 12=JAM
  set( "rol", "2A'22'--'26'36'--'--'32'2E'3E'--'--" ); // 22=JAM, 32=JAM
  set( "lsr", "4A'42'--'46'56'--'--'52'4E'5E'--'--" ); // 42=JAM, 52=JAM
  set( "ror", "6A'62'--'66'76'--'--'72'6E'7E'--'--" ); // 62=JAM, 72=JAM
  set( "stx", "--'--'--'86'--'96'--'92'8E'--'--'--" ); //         92=JAM, 8A=txa
  set( "ldx", "--'A2'--'A6'--'B6'--'B2'AE'--'BE'--" ); // AA=tax, B2=JAM
  set( "dec", "--'--'--'C6'D6'--'--'D2'CE'DE'--'--" ); // CA=dex, D2=JAM
  set( "inc", "--'--'--'E6'F6'--'--'F2'EE'FE'--'--" ); // EA=nop, F2=JAM

  set( "nop", "--'82'--'--'--'--'--'--'--'--'--'--" );
  set( "nop", "--'C2'--'--'--'--'--'--'--'--'--'--" );
  set( "nop", "--'E2'--'--'--'--'--'--'--'--'--'--" );

  set( "txa", "8A'--'--'--'--'--'--'--'--'--'--'--" );
  set( "tax", "AA'--'--'--'--'--'--'--'--'--'--'--" );
  set( "dex", "CA'--'--'--'--'--'--'--'--'--'--'--" );
  set( "nop", "EA'--'--'--'--'--'--'--'--'--'--'--" );

  set( "nop", "1A"); // 1 cycle
  set( "nop", "3A");
  set( "nop", "5A");
  set( "nop", "7A");
  set( "txs", "9A'--'--'--'--'--'--'--'--'--'--'--" );
  set( "tsx", "BA'--'--'--'--'--'--'--'--'--'--'--" );
  set( "nop", "DA");
  set( "nop", "FA");
  // 3,7,B,F

  set( "slo", "--'--'--'07'17'--'03'13'0F'1F'1B'--" ); // ASL + ORA (proper synthesis)
  set( "rla", "--'--'--'27'37'--'23'33'2F'3F'3B'--" ); // ROL + AND (proper synthesis)
  set( "sre", "--'--'--'47'57'--'43'53'4F'5F'5B'--" ); // LSR + EOR (proper synthesis)
  set( "rra", "--'--'--'67'77'--'63'73'6F'7F'7B'--" ); // ROR + ADC (proper synthesis)
  set( "sax", "--'--'--'87'--'97'83'--'8F'--'--'--" ); // AND(A,X) + store t to memory (register not changed); 93=SHA; 9B=SHS
 
  set( "lax", "--'AB'--'A7'--'B7'A3'B3'AF'--'BF'--" ); // LDA + LAX (proper synthesis)
  set( "las", "--'--'--'--'--'--'--'--'--'--'BB'--" ); // LAS = LDA+LAX + TXS
  set( "dcp", "--'--'--'C7'D7'--'C3'D3'CF'DF'DB'--" ); // DEC + CMP
  set( "isb", "--'--'--'E7'F7'--'E3'F3'EF'FF'FB'--" ); // INC + SBC

  set( "anc", "--'0B'--'--'--'--'--'--'--'--'--'--" ); // AND, and CF=result.7, aka. AAC
  set( "anc", "--'2B'--'--'--'--'--'--'--'--'--'--" ); // AND, and CF=result.7
  set( "asr", "--'4B'--'--'--'--'--'--'--'--'--'--" ); // AND, LSR (proper synthesis)
  set( "arr", "--'6B'--'--'--'--'--'--'--'--'--'--" ); // AND + ROR, also sets V. And C differently.
  set( "ane", "--'8B'--'--'--'--'--'--'--'--'--'--" ); // (A|0xEE) & x & t, set nz
  set( "sbx", "--'CB'--'--'--'--'--'--'--'--'--'--" ); // X = A&X - t; store to X
  set( "sbc", "--'EB'--'--'--'--'--'--'--'--'--'--" );
  set( "shy", "--'--'--'--'--'--'--'--'--'9C'--'--" ); // SHY/SYA/SAY
  set( "shx", "--'--'--'--'--'--'--'--'--'--'9E'--" ); // SHX/SXA/XAS
  set( "shs", "--'--'--'--'--'--'--'--'--'--'9B'--" ); // SHS
  set( "sha", "--'--'--'--'--'--'--'93'--'--'9F'--" );


EDIT: Just wanted to add that lidnariq' layout is exceptionally clear and nice.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 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