I'm looking at the Wombat machines some more. The issue now is whether to add a few of the
Wombat5w instructions to the Wombat4w and stick with that as the machine of choice for the compiler.
I should add some sort of interface to generate the instruction mnemonics, so that I can easily switch between load_ and loads, store_s and stores, for example.
The Wombat4 has call, return, load_s and store_s. The load_s and store_s access a specified location below or above the stack top.
The Wombat5 adds load_c to load a constant arithmetic value, copytop to load the stack top into an A register, and load_i and store_i to store into an arbitrary location in stack memory, indexed by a register. These could be used to start a heap at the other end of stack memory.
My Wombat4w just widens the instructions to address more memory, and adds the heap.
Why did I start the Wombat5w? Could I just add some of its features to the Wombat4w and leave it at that? Do I need load_c, copytop, and load_i and store_i? Should I leave the top register hidden, or use A7 for the stack top?
What do I need to be able to do?
- Load a constant value into a register.
- Load and store a value from the top frame of the stack into an array register. For this compiler, I should not need to access an arbitrary location on the stack. To do that, I would want load_i and store_i.
- Load and store a value from an object on the heap into an array register. For that, I will have an array with an object reference into the heap, and a fixed offset from that, calculated by the compiler, in the instruction. Then I have a value to store. That will use the load_h and store_h instructions that I added to the wombat4_w.
I'm going to try working with the Wombat4w instead of the Wombat5w and see if I can compile to that. First, I'll write up a description of the Wombat4w.
I need to change the source start bit of mdr->ir since mdr-> is wider than ir.
I should review the heap management functions that I wrote for Wombat4w and see what I did there.
Now I need to review the Wombat4w with a fine tooth comb and fix the problems that I have found.
I need to change the source start bit of mdr->ir since mdr-> is wider than ir.
Call instruction: ir(7-15)->pc looks wrong. This is because I was looking at Wombat4, not Wombat4w.
Review of Wombat4w
Registers
Registers look OK.
Register arrays
Register arrays look OK.
Condition bits
OK.
RAMs
OK.
Microinstructions
Set
clear-buf1 Used in alloc
clear-mar Used in store_h, load_h, load, store
clear-mdr Used in call
clear-pc Used in call, jump, jmpz, jmpn
These look OK.
Test
if(buf1!=0)skip-2 Used in jmpz
if(buf1>=0)skip-2 Used in jmpn
These look OK.
Increment
Inc3-pc Used in the fetch sequence
Inc4-top Used in call and push
dec4-top Used in return and pop
These look OK.
Shift
buf1 RSA 16 Used in loadc
Logical
None, OK.
Arithmetic
buf1*buf2->buf1 Used in multiply
buf1+buf2->buf1 Used in add
buf1-buf2->buf1 Used in subtract
buf1/buf2->buf1 Used in divide
mar+buf1->mar Used in store_h and load_h
top+mar->top Used in load_s and store_s, inctop
top-mar->top Used in load_s and store_s
These look OK.
Branch
None, OK.
TransferRtoR
buffer1->mdr (32 bits) Used in store_h, store_s, push, store
ir(11-23)->mar(3-15) (13 bits) Used in store_h and load_h
ir(8-23)->buf1(0-15) (16 bits) Used in loac_c
ir(8-23)->mar (16 bits) Used in store_s, load_s, load, store, inctop
ir(8-23)->pc (16 bits) Used in call, jump, jmpz, jmpn
mar->nextHeap (16 bits) Used in alloc
mdr(0-23)->ir (24 bits, 0-23) Used in the fetch sequence (fixed)
mdr(16-31)->pc (16 bits, 16-31) Used in return (fixed)
mdr->buffer1 (32 bits) Used in load_h, load_s, pop, load
nextHeap->buf1(16-31) (16 bits) Used in alloc
pc->mar (16 bits) Used in the fetch sequence
pc->mdr(16-31) (16 bits) Used in call (fixed)
top->mar (16 bits) Never used!
Renaming also:
Changed mdr(0-23)->ir to start at bit 0 (through bit 23, 24 bits)
Changed mdr(16-31)->pc to start at bit 16 (through bit 31, 16 bits)
Changed pc->mdr(16-31) to start target at bit 16 (through bit 31, 16 bits)
Changed mdr(8-31)->ir to mdr(0-23)->ir, move bits 0 through 23 (24 bits)
TransferRtoA
buf1->A[ir(21-23)] (32 bits) Used in pop, move, read
buf1->A[ir(5-7)] (32 bits) Used in load_h, load_s, load, add, subtract, multiply, divide
These look OK.
TransferAtoR
A[ir(21-23)]->buf1 (32 bits) Used in push and write
A[ir(21-23)]->buf2 (32 bits) Used in add, subtract, multiply, divide
A[ir(5-7)]->buf1 (32 bits) Used in store_h, store_s, move, add, subtract, multiply, divide, store, jmpz, jmpn
A[ir(8-10)]->buf1 (32 bits) Used in store_h and load_h
These look OK.
Decode
Decode-ir Used in fetch sequence
OK.
Set Condition Bit
set-halt-bit Used in stop
OK.
IO
input-int->buf1 Used in read
output-buf1->int Used in write
These look OK.
Memory Access
Heap[mar]->mdr Used in load_h
Main[mar]->mdr ?? Used in fetch sequence and load
Stack[top]->mdr Used in load_s, return, pop
mdr->Heap[mar] Used in store_h
mdr->Main[mar] Used in store
mdr->Stack[top] Used in store_s, call, push
Review fetch sequence! Fixed.
EQUs
A0-A7, OK.
Fields
None, OK.
Fetch Sequence
Fixed.
Machine Instructions
Everything looks OK for Wombat4w so far.
3:54 Are there any Wombat5w machine instructions that I should add to Wombat4w? These are the candidates.
copytop 16 Load the value of top into a register (for frame pointer-but need to increment it after the call, since the call pushes the pc??, or just leave it)
load_i 14 Load contents of place in stack indexed by one register into another
store_i 15 Store contents of one register into place in stack indexed by another
load_c 13 Load one (two) byte(s) from the instruction into a register.
alloc 42 Remember the current top of heap address. Copy the right half of a register into a short buffer: hold it, see below
inc 41 Increment a register by a fixed amount from the instruction (could be done by loading a value into a register, then adding, but that would cost a register)
Analysis of alloc as it currently is in Wombat5w
clear-buf2
nextHeap->buf2(16-31)
A[ir(7-9)](16-31)->abuf1
buf2->A[ir(21-23)]
abuf1+buf2->abuf1
abuf1->nextHeap
End
Clear buffer2 for next step.
Copy the current next heap address into the right half of buffer2.
(Now live: buffer2)
Copy the right half of the array register specified by the first operand into the short buffer abuffer1. ??
(Now live: buffer2 abuffer1)
Copy buffer2 into the array register specified by the second operand. This has the effect of remembering the previous next heap value in the register. ??
Add the contents of buffer2 to abuffer1. This leaves the sum of the previous next heap value (which was in buffer2) and the increment that was in the register specified by the first operand in abuffer1.
Copy the value in abuffer1 to nextHeap, which has the effect of incrementing nextHeap by the amount that was in the register specified by the second operand.
The effect of all this is:
Get the previous value of nextHeap in A[operand2].
Increment nextHeap by the right half of A[operand1].
Let's start cleaning up the code.
Initial state again:
clear-buf2
nextHeap->buf2(16-31)
A[ir(7-9)](16-31)->abuf1
buf2->A[ir(21-23)]
abuf1+buf2->abuf1
abuf1->nextHeap
End
Move store of buf2 into A[operand2] up one.
clear-buf2
nextHeap->buf2(16-31)
buf2->A[ir(21-23)]
A[ir(7-9)](16-31)->abuf1
abuf1+buf2->abuf1
abuf1->nextHeap
End
Let's get rid of abuf1.
clear-buf2 ;; new
nextHeap->buf2(16-31) ;; new
buf2->A[ir(21-23)]
A[ir(7-9)](16-31)->buf1
buf1+buf2->buf1
buf1(16-31)->nextHeap
End
We could get closer to our current microcode by swapping the roles of buffer1 and buffer2.
clear-buf1 ;; new
nextHeap->buf1(16-31) ;; new
buf1->A[ir(21-23)]
A[ir(7-9)](16-31)->buf2 ;; new
buf1+buf2->buf1
buf1(16-31)->nextHeap ;; new
End
Now make the first operand be 5-7 to have a 5 bit opcode.
clear-buf1 ;; new
nextHeap->buf1(16-31) ;; new
buf1->A[ir(21-23)]
A[ir(5-7)](16-31)->buf2 ;; new
buf1+buf2->buf1
buf1(16-31)->nextHeap ;; new
End
We could move things back to current registers a bit by using mar instead of buffer2.
Do I know in advance how much memory I need to allocate? If I do, I could simplify this to something like:
alloc ?? 5 3; 16
clear-buf1 ;; new
nextHeap->buf1(16-31) ;; new
buf1->A[ir(5-7)]
ir(8-23)->mar
mar+buf1->mar
mar->nextHeap ;; new
End
I think that I should add to my Wombat4w machine at least the load_c and alloc, possibly inc, and maybe load_i and store_i.
This is loadc from Wombat5w:
loadc 13 5 3 ; 16 0
ir(8-23)->buf1(0-15) ;; new
buf1 RSA 16 ;; new
buf1->A[ir(5-7)]
End
This is load_c from Wombat5:
load_c 13 5 2 ; 9 0
ir(7-15)->buffer1
buffer1>>7
buf1->A[ir(5-6)]
End
I would need to add the first two microinstructions. If I don't have this instruction, then I need to store values in Main memory somewhere in the middle of the code, possibly jumping over it, with stuff like
...
jump L1:
foo: .data 2 23 ;; data value
L1: ... ;; next instruction
...
load foo ;; use the value
...
I'm going to add the Wombat5w style microinstructions to Wombat4w to add load_c:
Under TransferRtoR:
ir(8-23)->buf1(0-15)
Under Shift:
buf1 RSA 16
Done.
Now I'll add the load_c instruction. I'll give it opcode 13 and change the opcodes of the other instructions. I'll change load_h and store_h to 1E and 1F.
CPUSim is acting a little weird. It is changing the values that I save in the fetch sequence. It also refused to add End at the end of an instruction.
I now want to add the alloc instruction.
The last setup that I had for it is:
alloc 16 5 3; 16
clear-buf1 ;; new
nextHeap->buf1(16-31) ;; new
buf1->A[ir(5-7)]
ir(8-23)->mar
mar+buf1->mar
mar->nextHeap ;; new
End
I'll need a new register, nextHeap. Added.
I'll need new microinstructions
Set
clear-buf1 Added
TransferRtoR
nextHeap->buf1(16-31) Added
mar->nextHeap Added
I'll need a new alloc instruction. I'll put it in the place of the copytop instruction with opcode 16. Added.
It is behaving strangely, and I have sent Dale Skrien an email about it.
I'll add my new instructions to my notes. Done.
Comments (0)
You don't have permission to comment on this page.