It is currently Thu Oct 19, 2017 12:23 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 84 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next
Author Message
PostPosted: Tue Mar 04, 2014 2:17 pm 
Offline

Joined: Sun Apr 04, 2010 4:28 pm
Posts: 91
As a thought experiment, I've been dreaming up a 16-bit CPU. My goal is to create a relatively powerful processor with a comprehensive instruction set, but is limited to working on 16-bits of data at a time. The specification, which is hosted at Github, is released to the public domain under the CC0 waiver, and anyone may use it for any purpose without permission or attribution. Direct link to the YCPU Specification.

I've also implemented an emulator for this processor in C#, which is released under the MIT license. The emulator is also hosted at Github.

In this thread, I've been asking questions as the specification has matured. Thanks to everyone who has offered comments and suggestions and answered my questions: this community is exceptionally helpful.


Last edited by pops on Sun Mar 23, 2014 9:44 pm, edited 22 times in total.

Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 2:19 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3192
Location: Mountain View, CA, USA
Recommend you look at the WDC 65816, which is a 16-bit CPU fully backwards-compatible with the 6502, to get an idea of what addressing modes are useful.


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 2:30 pm 
Offline
User avatar

Joined: Mon Feb 07, 2011 12:46 pm
Posts: 919
If R is register and I is immediate:
Code:
I
R
[R]
[R+I]
[R+[I]]
[[R]+I]
[--R]
[R++]

This might be a usable set of addressing modes (assume the stack pointer is one of the eight general purpose registers, possibly so is the program counter (in which case an immediate value addressing mode isn't needed)).

_________________
.


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 3:27 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19099
Location: NE Indiana, USA (NTSC)
You don't need to implement any addressing modes at all on most instructions. ALU operations such as addition can be register := register op register or register := register op constant. You only need addressing modes for the load and store instructions.

And even then, the only modes you really need are register+register and register+constant. Instead of having a more complicated address generator on the CPU, you can have the program running on the CPU calculate addresses with standard ALU instructions, which might let you run the rest of the CPU faster.

As for how offsets are interpreted: Is this 16-bit address space 65536 bytes (32768 words) or 65536 words? If 65536 bytes, what do you do with a 16-bit load from an odd address?


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 4:33 pm 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
Look at MIPS maybe: http://en.wikipedia.org/wiki/MIPS_architecture

It does things quite a bit differently then you may be used to if you only have knowledge of 6502 and may give you some ideas.


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 5:22 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
Having used both ARM and X86, ARM lets you do crazy stuff in address modes [r1 + r2 << r3], while X86 lets you use arbitrary memory with almost any instruction.

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 7:57 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19099
Location: NE Indiana, USA (NTSC)
Speaking of MIPS, I designed a 16-bit MIPS-inspired CPU called KIPS with 14 instructions while I was in college. (The thing was supposed to have 15, but I never got shift working.)

ALU ops: MOV, ADD, SUB, SLT (compare), AND, OR, XOR, two operands, second either a register or a 9-bit signed immediate value. These had two encodings: high nibble 8-F if the reg was
Other ops: LUI (load 16-bit immediate value shifted left 8; for use with OR to load a 16-bit value), LDR (load register with word at 6-bit offset from address in another register), STR (store), BNE/BEQ (add to PC if register is nonzero or zero), JSR (move PC to a register and add a 9-bit signed offset to PC), and RTS (move a register to PC). No flags; SLT puts the result in a register, and 32-bit quantities are added the same way 64-bit quantities are added on MIPS.

I seem to remember the instruction encoding looking something like this:
Code:
FEDCBA9876543210  ALU opcodes, second operand constant
||||||||||||||||
|||||||||||||+++- ALU function code inspired by 74*381 ALU:
|||||||||||||     0=shift, 1=compare, 2=subtract, 3=add,
|||||||||||||     4=xor, 5=or, 6=and, 7=mov (use second operand
||||||||||+++---- Destination register
|||||||+++------- Second operand
||||+++---------- First operand
++++------------- 0

FEDCBA9876543210  ALU opcodes
||||||||||||||||
|||||||+++++++++- Second operand, 9-bit signed
||||+++---------- First operand and destination
|+++------------- ALU function code
+---------------- 1

FEDCBA9876543210  LDR/STR
||||||||||||||||
||||||||||++++++- Offset from address
|||||||+++------- Register containing address
||||+++---------- Data register
++++------------- Memory opcode

FEDCBA9876543210  Conditional branches (whether or not a reg is nonzero)
||||||||||||||||
|||||||+++++++++- Signed value to add to PC if check succeeds
||||+++---------- Register to check
++++------------- Branch opcode


Top
 Profile  
 
PostPosted: Tue Mar 04, 2014 11:43 pm 
Offline

Joined: Sun Apr 04, 2010 4:28 pm
Posts: 91
koitsu wrote:
Recommend you look at the WDC 65816, which is a 16-bit CPU fully backwards-compatible with the 6502, to get an idea of what addressing modes are useful.
I'm thinking of a cpu with multiple general purpose registers, not an accumulator and two index registers. I realized while reading this document that despite months programming the 6502, I still have no idea what indexed indirect [ (value, x) ] addressing could be useful for, compared to indirect indexed [ (value),y ].

zzo38 wrote:
If R is register and I is immediate:
Code:
...
[--R]
[R++]
The inclusion of [R++] in place of Immediate addressing is clever. Sold. Where would I use --R?

tepples wrote:
As for how offsets are interpreted: Is this 16-bit address space 65536 bytes (32768 words) or 65536 words? If 65536 bytes, what do you do with a 16-bit load from an odd address?
I hadn't thought of this problem... and after spending the afternoon musing about it, I still have no idea what the correct solution is. My initial thought is that a 16-bit load from an odd address shouldn't be a problem, just load the low byte from the odd address and the hi byte from the even address.

Would the better solution be to ignore the bit0-address line when loading 16-bit? What about the PC? Loading [PC++] should evaluate to PC += 2, I guess. But that's completely counter-intuitive. How do other CPUs handle this?


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 12:04 am 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
pops wrote:
I still have no idea what indexed indirect [ (value, x) ] addressing could be useful for, compared to indirect indexed [ (value),y ].


It's generally pretty useless.


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 12:14 am 
Online

Joined: Sun Apr 13, 2008 11:12 am
Posts: 6280
Location: Seattle
pops wrote:
I still have no idea what indexed indirect [ (value, x) ] addressing could be useful for
Indexing into an array of pointers. e.g. C's argv[n][0].
Quote:
The inclusion of [R++] in place of Immediate addressing is clever. Sold. Where would I use --R?
PIC assembly includes a set of special registers (and instructions) that provide preinc, postinc, predec, and no change.
In any case, postinc and predec are obvious pairs for a software stack.
Quote:
Would the better solution be to ignore the bit0-address line when loading 16-bit? What about the PC? Loading [PC++] should evaluate to PC += 2, I guess. But that's completely counter-intuitive. How do other CPUs handle this?
IMO, you should forsake bytes altogether and natively address 65536 words.


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 12:25 am 
Offline
User avatar

Joined: Sun Jan 02, 2011 11:50 am
Posts: 522
lidnariq wrote:
Indexing into an array of pointers. e.g. C's argv[n][0].


But it only works in zero page .. zero page is normally too precious to waste on setting up arrays of pointers. Relevant discussion: http://forum.6502.org/viewtopic.php?f=2&t=2538


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 7:22 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19099
Location: NE Indiana, USA (NTSC)
I think the only place I've used (d,x) on the NES is in my music engine, where I store a bunch of data pointers per channel on zero page, indexed by channel X (where X=0, 4, 8, 12). In fact, apart from cases like this where you have multiple streams of data accessed in parallel, it's so otherwise unused that the Missile Command PCB repurposes it as a "screen access" instruction, with a circuit to recognize the (d,x) opcodes and temporarily remap the VRAM for individual pixel access.


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 7:35 am 
Offline
User avatar

Joined: Fri Nov 12, 2004 2:49 pm
Posts: 7230
Location: Chexbres, VD, Switzerland
Quote:
I think the only place I've used (d,x) on the NES is in my music engine, where I store a bunch of data pointers per channel on zero page, indexed by channel X (where X=0, 4, 8, 12).

Same here. Looks like this addressing mode is very specific to music ^^

I think it happened to me once to need plain indirect without indexing on 6502, and that I've used ($xx,X) instead of ($xx),Y because scrapping X was better than scrapping Y in that particular situation.


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 10:52 am 
Offline

Joined: Sun Apr 04, 2010 4:28 pm
Posts: 91
lidnariq wrote:
Quote:
Would the better solution be to ignore the bit0-address line when loading 16-bit? What about the PC? Loading [PC++] should evaluate to PC += 2, I guess. But that's completely counter-intuitive. How do other CPUs handle this?
IMO, you should forsake bytes altogether and natively address 65536 words.

That's an interesting idea - but that would completely preclude byte access. I suppose you could still emulate byte load and store with masking and shifting. But you would need an extra bit of address to select the hi or lo byte of a 16-bit word. What about chars and strings?

Here's an alternative, although I don't necessarily think it's better: data access is byte-aligned, instruction access is word-aligned. There's 0x10000 bytes of data and 0x8000 words of instructions which share the same space.


Top
 Profile  
 
PostPosted: Wed Mar 05, 2014 12:56 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3943
Separate instruction and data memory GO!

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 84 posts ]  Go to page 1, 2, 3, 4, 5, 6  Next

All times are UTC - 7 hours


Who is online

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