I've recently noticed spells when these pages come up with lots of hits from other sources, by far the most common is google, however, just now and then reddit becomes a source of my views, so I decided to take a look... I was happy, surprise and interested to see the threads... Lets take a look.
By far the most common of my posts to appear in reddit threads are tutorials, an interesting one, at least to me, is my 4001 CPU post. Of course it is a miss-noma for me to call it the 4001 a CPU... The intel 4001 was a ROM chip, the 4004 was the CPU in that series; strangely no-one spotted that intentional change, and I had thought they would.
Click here for the original post on this blog.
The post is about re-creating an integer CPU in code, it was a forerunner to a series for instructing a class, the next posts, which were planned were to include floating point mathematics, however, the whole series was put on hiatus, and I never returned to the topic.
ninereeds314 on reddit calls me out on this, about my commenting that about 486SX code, where I said:
"I know this because I once got told off for designing code with my 486SX2 processor - which could only add and subtract in hardware"
He says:
"No - even 8086 had integer multiply and divide instructions. They were slow enough that it was often worth avoiding them and using shift instructions and similar tricks if you could, and they could only work with the AX and DX registers (e.g. for multiply, AX x Source -> DX:AX) but they were there.
The 80386 32-bit versions of DIV, IDIV, MUL and IMUL were very similar, but working with EAX and EDX rather than just AX and DX where appropriate.
It was mostly the 8-bit chips that didn't have integer multiply and divide instructions. IIRC the Motorola 6809 was one of few 8-bit chips to actually have them, but came too late for the peak of 8-bit home computers - I think the best known machine it was used in was the Dragon 32.
Other than that, probably early RISC chips didn't have built-in multiply and divide instructions. One of the principles for RISC (at least years ago) was that every instruction should complete in one cycle, but multiply and divide needed a lot of transistors to do that - in practice they used microcoded algorithms (which was why they were slow)."
He is perfectly correct, my passing comment is slightly out of context, the 486SX could do integer multiplication and division as he says, it could not do floating point however, as it had a defective FPU which they disabled in the factory. This was what the SX was, a crippled DX, which Intel remarketed as a cheaper chip, rather than throw away.
My article however is about 8-bit code, and I wasn't clear, the 4004 could NOT do direct multiplication of integers, it performed the multiplication by looping, as I had done in my code for the 486SX. My solution for my code was quicker on the 486SX, which could do the integer add very quickly, but the multiplications were somewhat slower, over 100,000's of calls this did add up, so I avoided it; and in the article I'm only talking about an 8bit integer CPU. I wasn't clear enough.
However, choralone, comments directly after and spots what I meant, so I know I'm not completely lost.
This discussion continues between ninereeds, choralone and nerd4code, as they discuss more deeply what I'm describing, and indeed I see ninereeds explain that the x87 co-processors, were slower; here he's wrong, once the data was delivered across the FSB to the co-processor they were extremely fast, unfortunately the gated way in which data was shuffled to the cache on the co-processors meant that they were slower, they also only generally ran at 12Mhz, so processing on them compared to a 286 itself was fast, shuffling data to and from them, was quite slow. As it held the whole bus, with interrupts disabled.
The 387 co-processor was quicker, but could not use a 32bit bus, hence the 486 was designed to have the co-processor (redubbed an FPU) built in, but Intel had fabrication issues, and the photo-lithography techniques of the day left a lot of chips with perfectly functional integer cores, whilst the FPU's were defective... The answer, they severed the link to the FPU, relabelled it the SX and you had an emulating software library call, which vastly slowed the 486SX series down.
About this thread of discussion, I only wished they'd have had it on my actual blog... We like-minded people could have made firm friends!
On the same thread, we spin forward and the user "immibis" picks out my comment about where historically CPU's pick up their first instruction upon power on... he says he finds it hard to believe that they would pick a location in memory.
Well, they did, if a CPU picked 0x00 as it's start point, often it was not clear whether the CPU was reset, just powered, whether all the chips were ready, or the sync signal or whatever technology they had was ready, so it was common practice to have a all lines held low, and then raise on high along with the clock to indicate the start point of the CPU when it was literally first powered on, this high-line in early implementations (and indeed solid state machines before their being silicon) meant they didn't address zero, they in fact addresses a higher part of memory.... 0x800 was a common location for some machines I programmes for early on in my career.
Sometimes, as "jslepicka" points out, it was because the start of the address space was ROM, so the first instruction for execution was in ROM at memory address 2048, the preceding 2047 bytes had library calls, system calls and interrupt handling code in them. And they were (sometimes) in physically different ROM chips, which could and would be swapped on development machines or embedded devices, so you could upgrade the system calls, patches to calls in these early 2047 bytes often turned into JUMP instructions out to new patches in higher areas of memory beyond the start, and then a series of NO-OP instructions to stop them being used.
However, some early machines had all the RAM at the start, and the ROM on a different address space, so you had to pull a line high to get to ROM over RAM (or vice versa), so you had two different memory spaces to address. In those systems, you often had the problem that they were dodgy, memory was pretty daggy stuff, and chip failure rate high.
So, common practice, was to skip the first memory RAM chip at boot up, and use the second or third chips, according to the physical wiring diagram. So the first chip, which would for a matter of pico seconds (or nano seconds, or however long the electricity took to start to flow) have an "over current" or jolt, was NOT being used. As they genuinely tended to go bad more often, so much so it became routine for vendors, like Digital, to provide a book on how to actually make (with a soldering iron and logic chips!) your own replacement, or expansion memory!
Sometimes, as "jslepicka" points out, it was because the start of the address space was ROM, so the first instruction for execution was in ROM at memory address 2048, the preceding 2047 bytes had library calls, system calls and interrupt handling code in them. And they were (sometimes) in physically different ROM chips, which could and would be swapped on development machines or embedded devices, so you could upgrade the system calls, patches to calls in these early 2047 bytes often turned into JUMP instructions out to new patches in higher areas of memory beyond the start, and then a series of NO-OP instructions to stop them being used.
However, some early machines had all the RAM at the start, and the ROM on a different address space, so you had to pull a line high to get to ROM over RAM (or vice versa), so you had two different memory spaces to address. In those systems, you often had the problem that they were dodgy, memory was pretty daggy stuff, and chip failure rate high.
So, common practice, was to skip the first memory RAM chip at boot up, and use the second or third chips, according to the physical wiring diagram. So the first chip, which would for a matter of pico seconds (or nano seconds, or however long the electricity took to start to flow) have an "over current" or jolt, was NOT being used. As they genuinely tended to go bad more often, so much so it became routine for vendors, like Digital, to provide a book on how to actually make (with a soldering iron and logic chips!) your own replacement, or expansion memory!
There is also direct evidence of this in the books, of the skipping RAM and ROM, concepts... where you can still see references to the PWRUP functions, which established the power state (or power failure state) of AST (Async-System Trap) entry point addresses. These AST entry point addresses were never ever 0x00, because... well that's just all the lines pulled low, i.e. no-power, and not indicative of the power being on, or off or in any state really.
Of course, I reference things from way before the PC era, when computers still came with manuals on the actual logic gates within...
Thanks to AlexeyBrin for posting my blog to Reddit, and thanks to all those whom commented, I had fun reading this one.
So, do you plan on bringing this back? I am really interested in seeing where you would go with this! (sorry if double post, it was being weird and didn't actually post the first time).
ReplyDelete