Skip to content

Instantly share code, notes, and snippets.

@Zardoz89
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Zardoz89/e126fd9ced48b8e08a95 to your computer and use it in GitHub Desktop.
Save Zardoz89/e126fd9ced48b8e08a95 to your computer and use it in GitHub Desktop.
Changes to the next iteration of TR3200

We could take a simple stage model like ARM Cortex-M3 , ie 3 stages model : Fetch, Decode and Execute.

On Fetch stage :

  • Checks if there is a interrupt. If there are enabled and there is a interrupt handler for it, the CPU accepts it, initiating the interrupt sequence.
  • Reads 4 bytes from RAM
  • Increase PC by 4.

On Decode stage :

  • Decode instruction fetched on previus stage.
  • If the instruction have a long immediate value (M & L bits are 1)
    • Fetch next 4 bytes (32 bit immediate value)
    • Increase PC by 4
  • Sets input/output registers

Execute stage, well... executes it and writes to the output. If is a JMP or CALL instruction, obviously would overwrite PC register value.

Interrupt checking is doing on Fetch stage, before anything.

Interrupt sequence

When the CPU accepts an interrupt, the sequence must be :

  1. CPU puts IACK signal to High (ie, advice to devices that an interrupt is being attended)
  2. Gets the address from the table pointed by %ia
  3. Push to the stack the values of
    1. %r0
    2. if is a trap or a fault, %r1
    3. %flags
    4. Address
  4. Set %flags = %flags & 0xFFFFC0FF (ie, disables all Enable Interrupt/Trap/Fault)
  5. Sets %r0 to the interrupt message
  6. if is a trap or a fault, %r1 to the lenght on bytes of the fault/traped instruction
  7. Sets PC = %ia[0xFF & interrupt message]

When the CPU executes RFI to end an interrupt handler must be :

  1. Pop %pc
  2. Pop %flags
  3. If is a trap or a fault, %r1
  4. Pop %r0
  5. Set IACK signal to Low (ie, advices devices that the CPU has finished to attend an interrupt)

Software & Hardware interrupt

Keeps working like before. The address value pushed to the stack is next instruction to be executed (ie register PC value just at the end of Execute stage)

Traps

Traps are generated internally by the CPU and used to alert of something that an instruction did. Traps are reported ##immediately after the execution of the trapping instruction##.

The address value pushed to the stack is next instruction to be executed (ie register PC value just at the end of Execute stage)

Faults

Faults are generated internally by the CPU and used to alert the running kernel of an event or situation which requires its attention and can be corrected, so the program may continue as if nothing happened, or generate an error message. Faults have reserved the message valued 0xXXXXXX02 for highly critical and 0xXXXXXX03 for less critical .

The address value pushed to the stack is the address of the actual instruction being executed (ie register PC value before Fetch stage)

New interrupts

The CPU can now generate exceptions and faults interrupts for this cases :

Fault Message value
Invalid OpCode 0x00000002
(Reserved) 0x00000102
Unaligned LOAD/STORE 0x00000202
Unaligned PUSH/POP 0x00000302
(Reserved for Illegal address) 0x00000402
Division error (division by zero) 0x00000003
Trap Message value
Debug (single-step mode) 0x00000000
Overflow 0x00000001

Index auto increment

Add a "U" variant to LOAD/STORE instructions with 3 operand :

LOADUB Rd, Rs, Rn 
LOADUW Rd, Rs, Rn
LOADU  Rd, Rs, Rn

Were Rs = Rs + Rn BEFORE doing Rd = [Rs]

STOREUB Rs, Rn, Rd
STOREUw Rs, Rn, Rd
STOREU  Rs, Rn, Rd

Were Rs = Rs + Rn BEFORE doing [Rs] = Rd

Add an variant of Load isntruction with sign extend This two instructions does the same that LOADB and LOADW, but extends the sign, filling the most significant bits of the register with 0 or 1 on function of the sign of the read byte/word.

LOADSW   Rd, Rs, Rn
LOADSW   Rd, Rn

LOADSB   Rd, Rs, Rn
LOADSB   Rd, Rn

LOADUSB Rd, Rs, Rn 
LOADUSW Rd, Rs, Rn

In total are new 12 Load/Store instructions

SSLT and SLT (Set Signed Less Than & Set on Less Than) instructions are two 3 operand instructions with the two values to compare, plus a register were write the result of the comparison (0 or 1). It allow to do less comparision checks and do C subexpression like "a > b" more cheap.

Actually byte and word size math operations (add, sub, rsb) not have an carry or overflow flags. Carry flag for word and byte, not is highly necesary, as these bit could be extracted/compared on the result register, but the overflow condition is more complex. Doing it by software could carry an unfair penaly to word and byte wide math operations.

I propose add to %flag, this flag bits :

OBF : Overflow Byte Flag - Overflow condition on a 8 bit wide math operation
OWF : Overflow Word Flag - Overflow condition on a 16 bit wide math operation.

Were Overflow flags are calculted :

OF = A31 ^ B31 ^ CarryOut ^ Result31; OWF = A15 ^ B15 ^ Result16 ^ Result15; OBF = A7 ^ B7 ^ Result8 ^ Result7;

FLAGS should be :

BIT 31-16-> Reserved
BIT 15 -> Enable Division Error Fault (DEF)
Bit 14 -> Enable Unaligned Address Fault (UAF) (Enable/diasable LOAD/STORE and PUSP/POP faults)
BIT 13 -> Enable Invalid OpCode Fault (IOF)
BIT 12 -> Enable Faults (EF)
BIT 11 -> Reserved
BIT 10 -> Enable Overflow Trap (OT) (only 32 bit overflow)
BIT 9 -> Enable SingleStep Trap (ST)
BIT 8 -> Enable Interrupts (EI)

BIT 5-7 -> Reserved
BIT 4 -> Overflow Byte flag (OBF): 1 If an arithmetic 8 bit operation overflowed.
BIT 3 -> Overflow Word flag (OWF): 1 If an arithmetic 16 bit operation overflowed.
BIT 2 -> Division Error Flag: 1 If was a division error. (DE)
BIT 1 -> Overflow Flag: 1 If an arithmetic operation overflowed. (OF)
BIT 0 -> Carry Flag: 1 If the last ADDx/SUBx carried or borrowed a bit. (CF)
@milesrout
Copy link

You can disable interrupts, right?

@Zardoz89
Copy link
Author

You can switch on/off the interrupts touching a bit of %flags
Also, If an entry of the interrupt vector table is 0, (ie. not have a handler) is disabled.

%flags should have bits to enable/disable traps and exceptions (This a WIP document)

@milesrout
Copy link

If malicious code can just turn off interrupts, why do you need to have arbitrary if chain limits?

@Zardoz89
Copy link
Author

If malicious code can just turn off interrupts, why do you need to have arbitrary if chain limits?

Good point. Dropped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment