Copyright Information
Micron Instruction Set
Gen Design
Word Size: 32 bit
Instruction Size/Alignment: 4 bytes
Variable Sized Instructions: No
Common Flags/Condition Code Driven
Instruction format
8-bit (LSB) opcode followed 24-bit payload.
LSB First Order
Registers
Register Maps
There are 8 maps of registers:
- Map 0: General Purpose
- Map 1: System Configuration
- Map 2: I/O Transfer Registers
- Map 3: Information
- Map 4: Coprocessor Control
- Maps 8-15: Co-processor Registers.
There are 32 registers of each type. Except for Map 0, not all registers may be defined.
Co-processor Registers are available only if the applicable co-processors are connected.
Map 0: General Purpose
Assembly syntax: rn.
All Registers of the Map are defined. Certain Registers have special meaning:
r0is the zero-register. It reads as zero, and writes are ignored.
Map 1: System Configuration
Assembly syntax: sysn or alias.
Refer to the following table of defined registers. System Configuration Registers may be written only with values that meet register-specific constraints.
| Regno. | Aliases | Description |
|---|---|---|
| 0 | sysctl | System Control |
| 2 | inttab | Interrupt Table Pointer |
| 31 | intret | Interrupt Procedure return register |
Reading or Writing an undefined register causes EX[2]. Writing an invalid value to a defined register causes EX[5]
System Control (Map 1, Register 0)
Format:
+0-----------------------------31+
|i000000000000000000000000000000t|
+--------------------------------+
(All bits indicated as 0 must be written with 0)
| Bits | Name | Description |
|---|---|---|
i | Interrupt Enable (IE) | Only process IRQs when set to 1. |
t | Trap | Set to 1 by the processor when an Exception occurs. IRQs and Unit Error interrupts are not processed while this bit is set. Only cleared manually. |
Interrupt/Exception Table (Map 1, Register 2)
Format:
+0-----------------------------32+
|000aaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+--------------------------------+
(All bits indicated as 0 must be written with 0)
Bits a contain the 29 most significant bits of an 8-byte aligned address which points to the interrupt table. 512 bytes starting from this address refer to 64 8-byte entries of the interrupt table, which use the following format, in LSB-first order using little-endian byte encoding:
+0-----------------------------31+
|p0tttttttttttttttttttttttttttttt|
+32----------------------------63+
|00000000000000000000000000000000|
+--------------------------------+
The t bits are the 30 most significant bits of the address to transfer control to when the specified interrupt occurs.
The p bit must be set for all interrupt vectors that are present and valid to execute.
Interrupts
The first 16 interrupt entries are reserved for hardware exceptions, these interrupts are allocated as follows (and the nth entry in this list is designated elsewise as EX[n]):
- Entry
0: Exception Handling Fault - an exception is raised when thetflag is set. - Entry
1: Bus Fault - accessing memory in a particular manner causes an error, or attempts to access memory that doesn't exist. - Entry
2: Invalid Instruction - An instruction that is executed is an unknown opcode, reserved, malformed, or invalid - Entry
3: Unaligned Branch Target - an indirect branch is unaligned. - Entry
4: Consistency - An invalid system control register was loaded from memory, or an invalid value was written to a system register. - Entry
7: Non-maskable Interrupt - May be raised in response to a priority signal external to the processor that requires immediate resolution. This is handled like an IRQ, but does not obey theiflag. - Entries
8-15: Co-processor UnitnError - The corresponding Coprocessor unitnsignals an error after aCPIninstruction (nis Exception number - 4). - Entries
5,6, and16-31are reserved.
The remaining entries (32-63), may be allocated as IRQ vectors.
Exceptions are raised regardless of the i bit. The t bit is set to 1 when an exception is raised. It is not modified by any other interrupt (including an NMI) being raised.
If an exception occurs raising EX[0], the processor RESETs.
Interrupt Return Pointer (Map 1, Register 31)
When an interrupt occurs, this register is set to the value of the instruction pointer of the next instruction to execute - in the case of an IRQ or NMI, this is immediately after the last instruction to execute (or the jump target, if that instruction was a taken branch). In the case of an exception, this is the instruction that raised the exception.
In the case of EX[0], the value of this register is undefined.
Map 2: I/O Transfer Registers
Map 2 defines a sequence of input and output shift registers for transfering data to external peripherals.
Map 3: Information Registers
The Information Registers Map is a Read Only Map that contains information about the CPU. All Registers Presently Read 0. Writes are illegal and raise EX[2]
Map 4: Coprocessor Control
Each Co-processor has a 32-bit control word, which is defined by the Coprocessor.
Register N in Map 4 is defined if Co-processor N is present and enabled.
Reads and writes to an undefined register or a register corresponding to a not-present or disabled coprocessor results in EX[2].
Map 4, Register 30: Coprocessor Enable
The Coprocessor Enable register allows the system software to control what coprocessors are operating and usable from the CPU.
Format:
+0-----------------------------32+
|EEEEEEEE000000000000000000000000|
+--------------------------------+
The bits marked E may be set by the program when the corresponding bit of Register 31 is set. Setting the nth bit to 1 enables the coprocessor and setting it to 0 disables it.
Bits marked as 0 must not be written with 1.
Map 4, Register 31: Coprocessor Present
The Coprocessor Enable register allows the system software to determine what coprocessors are connected to the CPU. This register is read-only and cannot be written from the CPU. Attempting such a write with a MOV instruction raises EX[2].
Format:
+0-----------------------------32+
|PPPPPPPP000000000000000000000000|
+--------------------------------+
The nth bit is set to 1 if the nth coprocessor is present. Note that it is not guaranteed that the set of enabled coprocessors is contiguous or that the set of enabled coprocessors begins at 0.
Map 8-15: Co-processor Maps
Co-processors connected to the system may expose up to 32 registers each. Registers in map N are only defined if the coprocessor co-processor (Co-processor N-8) is enabled.
Instructions
Undefined Instructions
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
| UND | 0x00 | - |
| UND | 0xFF | - |
(The Payload bits are ignored by both instructions)
Timing (Execute Latency): 0 cycles
Exception Order:
EX[2](decode): Unconditionally
Behaviour: Unconditionally raises Invalid Instruction errors
instruction UND():
Raise(EX[2])
Pause
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
| PAUSE | 0x01 | kkkkkk000000000000000000 |
Timing (Execute Latency): 0 cycles + k
Behaviour: Delays execution for k cycles, 0-63
instruction PAUSE(k: u6):
SuspendForClockTicks(k)
Move
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------32 | |
| MOV | 0x02 | dddddsssss00lccccrmmmm00 |
Payload Bits Legend:
d: Destination Registers: Source Registerm: Mapr: Directionc: Condition Code (See Jump)l: Latency Control
Timing (Execute Latency): 1+c+t, where:
cis 0 if Condition Code is 0, 1 if Condition Code is 15 or Latency Control is 0 and the Condition Check Fails, 2 if Latency Control is 1 or the Condition Code is not 15 and the Condition Check Succeedstis 0 if Map is 0 or Latency Control is 0 and the Condition Check Fails, 2 if Map is not 0 when Latency Control is 1 or the Condition Check Succeeds.
Behaviour: Copies data between general purpose registers and to/from general purpose registers into other registers.
instruction MOV(d: u5, s: u5, m: u2, dir: u1, c: ConditionCode, l: bool):
if m!=0:
if dir==0:
ValidateRegisterReadable(m,d);
else:
ValidateRegisterWritable(m,d);
if CheckCondition(flags, c):
let ms, md: u2;
if dir==1:
md = m;
ms = 0;
else:
ms = m;
md = 0;
if md==3:
Raise(EX[2]);
let val: u32;
val = ReadRegister(ms, s);
if md == 2 or m > 3:
ValidateConfigurationRegisterValue(d, val);
WriteRegister(md, d, val);
else:
if l:
if m!=0:
SuspendForClockTicks(4);
else:
SuspendForClockTicks(2);
LD/ST
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------32 | |
ST | 0x03 | dddddsssssww00000000000p |
LD | 0x04 | dddddsssssww00000000000p |
LRA | 0x06 | dddddx00oooooooooooooooo |
Payload Bits Legend:
s: Source Registerd: Destination Registerw: Widthi: Immediate Valueo: Offseth: Hi/lo bitsq: Scale Quantityp: Push/Popx: Sign/Zero Extend
Timing:
ST,LD: 4 Cycles, plus Memory DelayLDI,LRA: 1 CycleSLDI: 2 cycles
Behaviour:
ST: Stores1 << wbytes fromdto[s]LD: Loads1 << wbytes from[s]intodLDI: Loads an immediateiinto the first (h=0) or upper (h=1) 16 bits ofdLRA: Loads the addressIP + o(ois a signed immediate ifxis true, and an unsigned immediate otherwise) intod.IPis taken from the beginning of the next instruction
instruction ST(s: u5, d: u5, w: u2, p: bool):
if d==0:
Raise(EX[2]);
let val = ReadRegister(0,s);
let addr: u32;
let width = 2 << w;
if width == 8:
Raise(EX[2]);
if p:
addr = ReadRegister(0,d) - width;
WriteRegister(0,d, addr);
else:
addr = ReadRegoster(0,d);
WriteAlignedMemoryTruncate(addr, val, width);
instruction LD(s: u5, d: u5,w: u2, p: u2):
if s==0:
Raise(EX[2])
let width = 2 << w;
if width == 8:
Raise(EX[2]);
let addr: u32;
addr = ReadRegister(0,s);
if p:
WriteRegister(0,s,addr + width);
let val = ReadAlignedMemoryZeroExtend(addr, w+1);
WriteRegister(0,s,val);
instruction LRA(d: u5, x: bool, i: u15):
let val = SignExtendOrZeroExtend(i, x) + IP;
WriteRegister(0,d,val);
Immediate Arithmetic
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
ADDI | 0x08 | dddddhcsiiiiiiiiiiiiiiii |
Timing: 2 Payload Bits Legend:
d: Destination Registerh: High halfs: Extend Signc: Supress Flags Modificationi: Immediate
Behaviour: Adds a 12-bit zero or sign-extended immediate to d.
ALU Instructions
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
ADD | 0x09 | dddddaaaaabbbbbcsssssp00 |
SUB | 0x0A | dddddaaaaabbbbbcsssssp00 |
AND | 0x0B | dddddaaaaabbbbbcsssssp00 |
OR | 0x0C | dddddaaaaabbbbbcsssssp00 |
XOR | 0x0D | dddddaaaaabbbbbcsssssp00 |
Timing: 2
Payload Bits Legend:
a: Source Register 1b: Source Register 2d: Destination Registerc: Suppress Conditionp: Shift Polaritys: Shift Quantity
Behaviour:
instruction {ADD, SUB, AND, OR, XOR}(a: u5, b: u5, d: u5, c: bool, s: u5, p: bool):
let src1, src2: u32;
if p:
src1 = ReadRegister(0, a) << s;
src2 = ReadRegister(0,b);
else:
src1 = ReadRegister(0, a);
src2 = ReadRegister(0,b) << s;
let dest: u32;
let flags_val, flags_mask: u4;
switch (instruction):
case ADD:
dest, flags_val = src1 + src2;
flags_mask = 0xF;
case SUB:
dest, flags_val = src1 - src2;
flags_mask = 0xF;
case AND:
dest = src1 & src2;
flags_val = LogicCondition(dest);
flags_mask = 0x3;
case OR:
dest = src1 | src2;
flags_val = LogicCondition(dest);
flags_mask = 0x3;
case XOR:
dest = src1 ^ src2;
flags_val = LogicCondition(dest);
flags_mask = 0x3;
if not c:
SetFlagsRegisterByMask(flags_mask, flags_val);
Butterfly Shifts
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
BSL | 0x0E | dddddvvvvvqqqqqcx0wrrrrr |
BSR | 0x0F | dddddvvvvvqqqqqcx0wrrrrr |
Timing: 3
Payload Bits Legend:
d: Destination Registerv: Input Valueq: Shift Quantityc: Suppress Conditionw: Wrap Quantityr: Shift Remainder (Input value)x: Invert by Sign
Behaviour: Shifts v by q and places the value in
Branches
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
JMP | 0x10 | cccclllllooooooooooooooo |
JMPR | 0x11 | cccclllllrrrrr0000000000 |
Payload Bits Legend:
c: Condition Codel: Link Registero: Destination Offset (Bits 2..17)r: Destination Register
Timing: 2+t+l+r where:
tis1if the branch is taken and0if it is not takenlis1if Link Register is non-zero and the branch is taken, and0otherwiseris1forJMPRand0forJMP
Behaviour: Jumps to the destination, if the condition is satisfied, saving the return address in l if taken:
JMP: The offset isIP + o * 4whereois a signed offset.IPis the same as the return address and points to the beginning of the next instructionJMPR: The offset is read fromr
instruction JMP(c: ConditionCode, l: u5, o: u15):
let disp = SignExtend(o) << 2;
let curr_ip = IP;
if CheckCondition(flags, c):
if l != 0:
WriteRegister(0,l, curr_ip);
IP = curr_ip + disp;
instruction JMPR(c: ConditionCode, l: u5, r: u5):
let addr = ReadRegister(0,r);
if addr & 3 != 0:
Raise(EX[3]);
let curr_ip = IP;
if CheckCondition(flags, c):
if l != 0:
WriteRegister(0,l, curr_ip);
IP = addr;
Condition Code
JMP, JMPR, and MOV all use a 4-bit condition code to encode the branch condition. This includes conditions for "Always" and "Never".
enum ConditionCode is u4:
Never = 0,
Carry = 1,
Zero = 2,
Overflow = 3,
CarryOrEqual = 4,
SignedLess = 5,
SignedLessOrEq = 6,
Negative = 7,
Positive = 8,
SignedGreater = 9,
SignedGreaterOrEq = 10,
Above = 11,
NotOverflow = 12,
NotZero = 13,
NotCarry = 14,
Always = 15
function CheckCondition(flags: u32, c: ConditionCode) is bool:
switch (c):
case Never:
return false;
case Carry:
return (flags & 0x80) != 0;
case Zero:
return (flags & 0x01) != 0;
case Overflow:
return (flags & 0x40) != 0;
case CarryOrEqual:
return (flags & 0x81) != 0;
case SignedLess:
return (((flags & 0x40) != 0) == ((flags & 0x02) != 0)) and (flags & 0x01) == 0;
case SignedLessOrEq:
return (((flags & 0x40) != 0) == ((flags & 0x02) != 0)) or (flags & 0x01) != 0;
case Negative:
return (flags & 0x02) != 0;
case Positive:
return (flags & 0x02) == 0;
case SignedGreater:
return not ((((flags & 0x40) != 0) == ((flags & 0x02) != 0)) or (flags & 0x01) != 0);
case SignedGreaterOrEq:
return not ((((flags & 0x40) != 0) == ((flags & 0x02) != 0)) and (flags & 0x01) == 0);
case Above:
return (flags & 0x81) == 0;
case NotOverflow:
return (flags & 0x40) == 0;
case NotZero:
return (flags & 0x01) == 0;
case NotCarry:
return (flags & 0x80) == 0;
case Always:
return true;
Behaviour:
- Multiplies
I/O Transfers
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
IN | 0x14 | dddddpppppppp000000wwwww |
OUT | 0x15 | ssssspppppppp000000wwwww |
Payload Bits Legend:
- s: Source Transfer Register
- d: Destination Transfer Register
- w: Transfer Bit Width
- p: Port Number
Timing: 7 + Port Delay
Behaviour: Shift w bits in an io transfer register in or out to an I/O Port
IN: Shifts bits into the high bits of the transfer registerOUT: Shifts bits out of the low bits of the transfer register
instruction IN(s: u5, p: u8, w: u5):
let val = RotateRight(ReadBitsFromPort(p,w),w);
let regval = ReadRegister(2,s) >> w;
WriteRegister(2,s, val | regval);
instruction OUT(s: u5, p: u8, w: u5):
let regval = ReadRegister(2,s);
let val = regval & ((1 <<w)-1);
WriteRegister(2, s, regval >> w);
WriteBitsToPort(val, p, w);
Flags Manipulation
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
LDFLAGS | 0x18 | ddddd0000000000000000000 |
STFLAGS | 0x19 | sssss0000000000000000000 |
Payload Bits Legend:
- s: Source Register
- d: Destination Register
Timing: 1
Behaviour:
LDFLAGSloads the flags bits into the lower 4 bits ofd(zero extended)STFLAGSstores the lower 4 bits ofsinto the flags bits
The Flags Bits are:
0--3 |
|---|
cvnz |
c: Carryv: Signed Overflown: Negativez: Zero
instruction LDFL(d: u5):
let val = flags;
WriteRegister(0,d, val);
instruction STFL(s: u5)
let val = ReadRegister(0, s);
flags = val & 0xF;
Invoke Coprocessor Unit
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
CPIx | 0x20+x | ffffpppppppppppppppppppp |
NCPIx | 0x28+x | ffffpppppppppppppppppppp |
CPIxEF | 0x30+x | ffffffpppppppppppppppppp |
NCPIxEF | 0x38+x | ffffffpppppppppppppppppp |
(x is a value from 0 to 7, representing the co-processor number to invoke, for example, CPI0 has opcode 0x20 and NCPI7 has opcode 0x2F)
Timing: 2 + N where:
- For
CPIxandCPIxEF,Nis the delay in cycles before the co-processor becomes ready to execute again - For
NCPIxandNCPIxEF,Nis 0.
Payload Bits Legend:
f: Co-processor functionp: Co-processor instruction payload
Behaviour: Executes the specified Coprocessor function with the specified payload
CPIx/CPIxEF: Waits for the Co-processor to finish all operations, and raises the appropriate unit error if the Coprocessor reports it,NCPIx/NCPIxEF: Finishes immediately.CPIx/NCPIx: Allows specifying up to 16 functions with a 20-bit payloadCPIxEF/NCPIxEF: Allows specifying up to 64 functions with a 18-bit payload (bottom 18-bits of the 20-bit payload)
instruction {CPI0, CPI1, CPI2, CPI3}(f: u4, p: u20):
let coproc: u4;
switch (instruction):
case CPI0:
coproc = 0;
case CPI1:
coproc = 1;
case CPI2:
coproc = 2;
case CPI3:
coproc = 3;
if not IsCoprocessorEnabled(coproc):
Raise(EX[3]);
ExecuteCoprocessorInstruction(coproc, f, p);
WaitOnCoprocessor(coproc);
if PullCoprocessorException(coproc):
Raise(Ex[4+coproc]);
instruction {CPI0EF, CPI1EF, CPI2EF, CPI3EF}(f: u6, p: u18):
let coproc: u4;
switch (instruction):
case CPI0EF:
coproc = 0;
case CPI1EF:
coproc = 1;
case CPI2EF:
coproc = 2;
case CPI3EF:
coproc = 3;
if not IsCoprocessorEnabled(coproc):
Raise(EX[3]);
ExecuteCoprocessorInstruction(coproc, f, p);
WaitOnCoprocessor(coproc);
if PullCoprocessorException(coproc):
Raise(Ex[4+coproc]);
instruction {NCPI0, NCPI1, NCPI2, NCPI3}(f: u4, p: u20):
let coproc: u4;
switch (instruction):
case NCPI0:
coproc = 0;
case NCPI1:
coproc = 1;
case NCPI2:
coproc = 2;
case NCPI3:
coproc = 3;
if not IsCoprocessorEnabled(coproc):
Raise(EX[3]);
ExecuteCoprocessorInstruction(coproc, f, p);
instruction {NCPI0EF, NCPI1EF, NCPI2EF, NCPI3EF}(f: u6, p: u18):
let coproc: u4;
switch (instruction):
case NCPI0EF:
coproc = 0;
case NCPI1EF:
coproc = 1;
case NCPI2EF:
coproc = 2;
case NCPI3EF:
coproc = 3;
if not IsCoprocessorEnabled(coproc):
Raise(EX[3]);
ExecuteCoprocessorInstruction(coproc, f, p);
Halt/Stop CPU
| Mnemonic | Opcode | Payload |
|---|---|---|
0--7 | 8---------------------31 | |
HALT | 0x40 | 000000000000000000000000 |
STOP | 0x41 | 000000000000000000000000 |
Timing:
HALT: 1STOP: N/A
Behaviour: Places the CPU in a low-power state and stops executing
HALT: Execution resumes after an NMI, IRQ (if enabled), Unit Error (ifsysctl.t=0), or RESET.STOP: Execution resumes after a RESET only. No other interrupts are serviced.
instruction HALT() {
SetStatus(2);
WaitForInterrupt();
}
instruction STOP() {
SetStatus(3);
ShutdownCpu();
}
Initial State
Execution Address
The CPU begins executing from address 0xFF00.
Register Contents
- GPR, I/O Transfer, and Coprocessor Registers are undefined
- System Registers are set according to the following:
sysctl: All bits 0copctl: P bits set according to which Coprocessors are connected. Other bits are 0inttab: 0intret: Undefined
Copyright
Floating Point Co-processor Unit
Unit Configuration
The 6-bit field in the co-processor control register is set as follows. After writing to it on the CPU side, there is a 6 cycle execution delay before the unit becomes ready. If the unit is busy when the CPU writes to these bits, the Unit signals a Unit Error (Configuration Error) immediately. Pending Instructions are disposed of.
Format:
+0----5+
|i00000|
+------+
When i is set, The Integer Op Extended Functions are enabled to operate on fpi registers.
Registers
Within the Co-processor Register Map, the following registers are defined:
- Registers 0-15 are floating-point registers, designated by name
fpn - Registers 16-23 are co-processor local integer registers, designated by
fpinwherenis the register number - 16. - Registers 24-31 are Unit Status Registers specified below, designated by
fpcnwherenis register number - 24, or an alias.- Writes to these registers from the CPU incur a 2 cycle execution delay before the unit becomes ready. This delay is ordered properly with pending instructions, and a Unit Error is not signaled if the unit is busy.
- A subsequent write to any of these registers without an intervening instruction on the unit disposes of the previous write if it is still pending.
Unit Control/Status Registers
FP Unit Error/Operation Register (Register 24)
fpc0 or fpuop (Register 24) is the FPU Unit Error/Operation Register.
This register can be overwrriten with 0. Overwriting with any other value raises a Unit Error (STATUS ERROR).
The Register is 0 when the unit is first enabled, and becomes 0 after the configuration is changed or the unit is disabled and reenabled.
Format:
+0-----------------------------31+
|xxxzzzzzzzzzzzzzruiiiiiiiiiiiiii|
+--------------------------------+
x is set to the unit error number on an unit error, or 0 if there hasn't been a unit error since the last time the register was reset to 0.
i contains the low 16-bits (with the 2 least significant bits discarded) of the most recently begun Unit Instruction.
u is set to 1 if any Unit Instruction has been issued since the register was last reset to 0. This includes if the instruction is still pending or in-progress.
r is set to 1 if the unit is currently busy, and 0 otherwise. Note that an instruction like FPSTREG will always observe this bit being 0, but a CPU issued MOV to map 0 can read the bit as 1.
Bits indicated by z are unused and must be ignored by programs.
Error Numbers
- Error 1 (FPE): A previous floating-point computation or status check signaled an unmasked floating-point exception
- Error 2 (INVALID INSTRUCTION): An undefined or invalid unit instruction was issued
- Error 3 (STATUS ERROR): An invalid value was written to a status register
FP Control/Status Register (Register 25)
fpc1 or fpcsr is the Floating-Point Control and Status Register.
Format:
+0-----------------------------31+
|cccczouidvzzzzzz00000O̅U̅I̅D̅V̅0000rr|
+--------------------------------+
Bits indicated by 0 must be written with 0 or STATUS ERROR is thrown. Bits indicated by z must not be overwritten (may cause STATUS ERROR), and must be ignored by programs.
Bits c contain the status flags from the most recent comparison op. Integer comparisons and Bitwise TEST use the same format as the flags register for the primary ISA.
Floating point partial-order comparison use the format eltk, which is set as follows:
eis set to the partial-order equalitylis set to the partial-order less-thantis set to the total-order less-thankis set to unordered.
Floating-point total-order comparisons use the format EL0K, which is set as follows:
*
Bits o, u, i, d, v are set by floating-point operations that signal an FP Exception.
Bits O̅, U̅, I̅, D̅, and V̅ are control bits that determine exception masking. When set to 0, the corresponding floating-point exception is masked and does not trigger Error 1. When set to 1, the corresponding exception is raised. The exceptions are:
- Numeric Overflow (bits
o(indication) andO̅(masking)) - Numeric Underflow (bits
u(indication) andU̅(masking)) - Inexact Result (bits
i(indication) andI̅(masking)) - Divide by Zero (bits
d(indication) andD̅(masking)) - Invalid Operation (bits
v(indication) andV̅(masking))
r is the dynamic rounding mode, set as follows:
0is Round to Nearest, Ties Even1is Round to Zero2is Round To +∞3is Round to -∞
Unit Functions
Notes about CPIxEF
CPIxEF allows up to 64 functions (instead of 16-bits) to be uniquely invoked at the cost of the top 2 bits of the payload being forced to 0.
All unit functions that encode a rounding mode store the static rounding control in the top 2 bits. Thus invoking these functions with CPIxEF cannot select a static rounding mode other than "Round to Nearest, Ties Even" (rounding mode 0). These instructions can still select a dynamic rounding control, and a rounding control other than mode 0 can be set in fpcsr.
Other unit functions do not use the top two bits of the payload.
Functions that rely on the rounding mode and that are only accessible to CPIxEF (function numbers > 0x0F) do not support static rounding control.
Pause FPU
| Mnemonic | Function | Payload |
|---|---|---|
0--6 | 0-----------------19 | |
FPAUSE | 0x00 | kkkk0000000000000000 |
Timing (Execute Latency): 0 cycles + k
Behaviour: Delays execution for k cycles, 0-15
instruction PAUSE(k: u4):
SuspendForClockTicks(k)
Move FP Register
| Mnemonic | Function | Payload |
|---|---|---|
0--6 | 0-----------------19 | |
FPMOV | 0x01 | sssssdddddcccc000000 |
Moves between floating-point registers. The MOV is bitwise if it succeeds.
Payload bit legend:
s: Source Register Numberd: Destination Register Numberc: Condition Code
Condition Code is interpreted the same way as for the MOV CPU Instruction, but it reads from fpcsr instead of flags
Timing: 1+c, where:
cis 0 if Condition Code is 0, 1 if Condition Code is 15 or the Condition Check Fails, 2 the Condition Code is not 15 and the Condition Check Succeeds
instruction FPMOV(s: u5, d: u5, c: ConditionCode):
if CheckCondition(fpcsr & 0xF, c):
let val: u32;
val = ReadRegister(UNIT, s);
WriteRegister(UNIT, d, val);
CheckAndThrowPendingUnitErrors();
Floating-point Conversions
| Mnemonic | Function | Payload |
|---|---|---|
0--6 | 0-----------------19 | |
CVTF2F | 0x04 | ssssddddffkk00000yrr |
CVTI2F | 0x05 | sss0ddddi0kk00000yrr |
CVTF2I | 0x06 | ssssddd0ffi000000yrr |
Payload bit legend:
s: Source Register Number (FP Register)d: Destination Register Number (FP Register)f: Source Floating-point Formatk: Destination Floating-point Formaty: dynamic rounding control.r: Static rounding mode.i: Signed Integer
Timing:
- For
CVTF2F, Iffandkare the same format: 1 Cycle, - For
CVTF2F, Iff>k: 3 Cycles, - Otherwise: 5 Cycles.
enum FloatFormat:
FP16 = 0,
FP32 = 1,
instruction CVTF2F(s: u4, d: u4, f: FloatFormat, k: FloatFormat, y: bool, r: RoundingMode):
let rnd = y ? r : fpcsr >> 30;
let val = ReadRegister(UNIT, s);
let rounded = FpRoundToFormat(val, f, k, rnd);
WriteRegister(UNIT, d, rounded);
CheckAndThrowPendingUnitErrors();
instruction CVTI2F(s: u3, d: u4, i: bool, k: FloatFormat, y: bool, r: RoundingMode):
let rnd = y ? r : fpcsr >> 30;
let val = ReadRegister(UNIT, s);
let rounded = FpRoundIntToFormat(val, i, k, rnd);
WriteRegister(UNIT, d, rounded);
CheckAndThrowPendingUnitErrors();
instruction CVTF2I(s: u4, d: u3, i: bool, f: FloatFormat, y: bool, RoundingMode):
let rnd = y ? r : fpcsr >> 30;
let val = ReadRegister(UNIT, s);
let rounded = FpRoundToInt(val, i, k, rnd);
WriteRegister(UNIT, d, rounded);
CheckAndThrowPendingUnitErrors();
Floating-point arithmetic
| Mnemonic | Function | Payload |
|---|---|---|
0--6 | 0-----------------19 | |
FADD | 0x08 | ddddaaaabbbb00000yrr |
FSUB | 0x09 | ddddaaaabbbb00000yrr |
FMUL | 0x0A | ddddaaaabbbb00000yrr |
FFMA | 0x0B | ddddaaaabbbbcccc0yrr |
instruction FADD()
Copyright
psABI
Types
C Primitive Sizes
CHAR_BIT is 8.
| Type | Size |
|---|---|
bool1 | 1 |
short | 2 |
int | 4 |
long | 4 |
long long | 8 |
float | 4 |
double | 8 |
long double | 8 |
void* | 4 |
intptr_t | 4 |
size_t | 4 |
intmax_t | 8 |
wchar_t | 2 |
Char Types
char is unsigned by default.
Primitive Alignment
The Size and alignment of align_max_t are both 4. Each primitive less than or equal to 4 bytes in size is aligned to its size, rounded up to the next power of two bytes.
Each primitive that is greater than 4 bytes in size are aligned to 4 bytes. This includes _BitInt(N) types.
Floating Point Formats
float matches the IEEE754 binary32 format.
double and long double both match the IEEE754 binary64 format.
Registers
In Map 0, Registers r1-r15 are callee saved and are not preserved accross prodecure calls. Registers r16-r31 are caller saved and must be restored to their values at entry by the function. r0 is a constant 0 register and cannot be modified.
r15 is recommended for use by code patterns that use a register to compute a value for immediate use. The Assembler may make use of this register implicitly to assemble certain psuedo-instructions.
Map 1 Registers should not be modified by toolchains, except through explicit arrangement with the program. The precise values of Map 1 Registers should not be relied upon.
Registers in Map 2 and Maps 4-7 are callee saved and are not preserved accross procedure calls.
r1 and r2 are used to return values up to 8 bytes in size. Registers r1 through r10 are used to pass up to 10 parameters.
Register Overview
| Register(s) | Purpose | Callee/Caller Saved |
|---|---|---|
r0 | Constant 0 | Constant Register |
r1 | Param/Return Register | Caller Saved |
r2 | Param/Return Register | Caller Saved |
r3-r10 | Param Register | Caller Saved |
r11-r14 | Scratch Register | Caller Saved |
r15 | Special-Purpose Scratch Register | Caller Saved |
r16-r27 | Callee Saved Register | Callee Saved |
r28-r29 | Reserved Register | Callee Saved/Reserved |
r30 | Stack Pointer | Callee Saved |
r31 | Return Pointer | Callee Saved |
Stack, Link Register, Reserved Registers
Map 0 Registers r28, r29, r30, and r31 are reserved for special use, within the caller saved regions.
r28 and r29 are not used by this ABI, but may be used by future versions or by individual machines/systems/programs as a special registers. If modified by software complying with this ABI, it must be restored before returning from the current procedure or entering another procedure, unless it is modified in cooperation with the definition of the register.
[!NOTE] It is recommended for r28 to be used as a Thread Pointer on a multicore system.
r30 is reserved to be the stack pointer. Before entering a procedure, it must refer to a memory address which points to the end of a memory region that is available for the procedure to use to store its own variables and parameters. The Address must be aligned to 4 bytes, and must be mutable. Additionally, the memory region immediately following the pointers may be required to hold parameters passed on the stack. The stack grows downwards, away from the end of the region allocated for the stack. Any region of memory between the address in r30 up to the end of the stack shall be preserved by compliant software, unless mutated via a pointer. All memory below the stack pointer in the allocated memory region may be freely clobbered at any point (including by an interrupt handler) and must not be relied upon in any particular value.
r31 is reserved to be the standard link register. Upon entry to any procedure, r31 shall contain the address to return to upon exit.
[!NOTE] While r31 remains caller saved, every function call that isn't a tailcall will necessarily modify this register and require the register to be spilled to memory. The exception is if the function does not expect to return.
Parameter Passing/Return Convention
When passing or returning values, each value is classified as follows:
- Primitive Values,
- Non Trivial Aggregates
Non-Trivial Aggregates are types with an alignment greater than 4, or a class type C++ with one of the following special member functions being non-trivial, and which is not trivially relocatable:
- Copy or Move (Since C++11) Constructor,
- Destructor.
All types that are not Non-Trivial Aggregates, and only have fields or elements of Primitive types (recursively) are Primitive Values.
Each parameter/return value in order is assigned a passing mode: * If the paramater/return value is larger than 8 bytes in size, it is passed/returned in memory, * If the parameter/return value is a Non-Trivial Aggregate, it is passed/returned in memory, * Otherwise, it is passed directly/returned.
If the return value is returned in memory, an implicit first parameter is inserted, which is a pointer to storage suitable for placing the entire return value. This pointer is then returned in r1.
A parameter passed in memory is replaced with a single 4 byte value passed directly, which points to the memory used to pass the value.
After replacement, values passed/returned directly are divided into up to 2 4-byte chunks. Any chunk which is not present or consists entirely of padding bytes is discarded when passing directly. Then, each chunk in parameter order (with least significant byte first) is passed by allocating the next available register in r1-r10. If any chunk of a parameter cannot be allocated a register, the entire value is pushed to the stack in Right to Left Order (with the Leftmost parameter occupying the least significant address). The most significant address of the parameter area is 4 byte aligned, and up to 3 bytes are inserted after the leftmost parameter to align the stack to 4 bytes. Padding is inserted between parameters to align each parameter to the smaller of their size rounded up to the next power of 2, and 4 bytes. Once the first parameter is passed on the stack, no further parameters are passed in registers.
Each returned chunk of the return value is returned in the first available register of r1 and r2.
Floating point co-processor
The Use of a hardware floating-point coprocessor to compile floating-point operations is permitted. Due to variability in machine allocations, the co-processor used for floating-point operations is not specified herein, and must be specified by the appropriate machine supplement or toolchain configuration options. Use of a particular co-processor number with hardware floating-point operations is not compatible with a system that does not have a floating-point co-processor in the appropriate slot.
Regardless of the use of a floating-point co-processor, floating-point values are not passed using floating-point registers, and are still passed using general purpose parameter registers when <= 8 bytes in size.
ELF Files
OSABI
The following OSABI values are defined
| OSABI | Constant | Description |
|---|---|---|
0-63 | Multiple | See gABI OSABI list |
255 | OSABISTANDALONE | Standalone/Freestanding target |
Copyright
-
Referred to as
_Boolin C since C99 until C23. ↩
Assembly Syntax
Operands
The following operand syntax types are used in instructions
| Short | Name | Description |
|---|---|---|
GPR | GPR operand | A General Purpose Register |
SGPR | Shifted GPR operand | A General Purpose Register Left-shifted by a constant |
IOR | I/O Register operand | An I/O Transfer Register (Map 3) |
ANYREG | Any Register | Any Register operand |
UIMM16 | Immediate (unsigned 16-bit) | 16-bit Immediate operand |
SIMM16 | Immediate (signed 16-bit) | 16-bit Immediate operand |
PCREL16 | PC Relative Address (16-bit) | 16-bit offset from IP in bytes |
OFF20 | Jump Offset (signed 20-bit) | 20-bit jump offset in words |
UIMM32 | Immediate (unsigned 32-bit) | 32-bit immediate operand |
SIMM32 | Immediate (signed 32-bit) | 32-bit immediate operand |
BITW | Bit Width | Width of a value in bits |
BYTESZ | Byte Size | Size of a value in bytes |
ABSIMM2 | Immediate (unsigned 2-bit) | 2-bit absolute (non-relocated) immediate |
ABSIMM5 | Immediate (unsigned 5-bit) | 5-bit absolute (non-relocated) immediate |
ABSIMM6 | Immediate (unsigned 6-bit) | 6-bit absolute (non-relocated) immediate |
ABSIMM8 | Immediate (unsigned 8-bit) | 8-bit absolute (non-relocated) immediate |
CC | Condition Code Name | A condition Code |
GPR operands
A GPR operand is written as r followed by the index number of the register.
Shifted GPR
A Shifted GPR operand is written as GPR << ABSIMM5
I/O Register Operand
An I/O Register Operand is written as io followed by the index number of the register.
Any Register
A Register in any map is either a GPR operand, and I/O Register operand, a system configuration register, a system information register, or a coprocessor register.
A system configuration register is written as either sys followed by the index number of the register or the alias name specified in the ISA (for example, the System Control Register may be written as sys0 or sysctl).
A system information register is written as info followed by the index number of the register.
A coprocessor register is written as co followed by the coprocessor number between 0 and 3, followed by r, followed by the register number.
If the Assembler is aware of the particular coprocessor expected in a given coprocessor slot, it may use the alias name provided by the Coprocessor's Assembly Supplement.
For example, if the Assembler is aware of the presence of a FPU (according to <float-coproc.md>) in slot 0, it may alias f0 as co0r0.
Immediates
Immediate operands take an integer or a symbol. n-bit Unsigned Immediates require an unsigned quantity in [0,2^n). Signed Immediates require a signed quantity in [-2^(n-1), 2^(n-1)).
Other than Absolute Immediates (like ABSIMM6), immediate operands can have symbols. Unless specified with the @pcrel modifier, Immediate operands always treat symbols as absolute address in relocations. The relocation requires that the address fits in the specified size of immediate (a link error occurs if it does not). using the special modifiers HI and LO allows you to instead specify the lower or upper 16-bits of the symbol.
Unless modified, immediate relocations uses (given the appropriate n):
R_MICRON_<n>R_MICRON_LO16(LO <sym>)R_MICRON_HI16(HI <sym>)
With the @pcrel modifier (or for PCREL16, see below), the relocation uses (given the appropriate n):
R_MICRON_PC16R_MICRON_LOPC16(LO <sym>@pcrel)R_MICRON_HIPC16(HI <sym>@pcrel)
Offsets
The PCREL16 and OFF20 values are special cases of immediates.
PCREL16 is identical to a SIMM16 relocation, except that it defaults to resolving the specified symbol using a pc-relative relocation.
OFF20 is a 20-bit immediate that resolves a 22-bit pc-relative relocation or a 22-bit signed integer offset, and discards the lower two bits to encode the instruction. It has two constraints, in addition to the constraints that would apply to a 22-bit signed immediate:
- Absolute Expressions must be divisible by 4, and
- Relocation Expressions must produce a 4-byte aligned quantity. The Assembler may error if a misalignment is reliably detected (for example, a 3-byte offset from a symbol known to be 4-byte aligned).
OFF20 uses R_MICRON_JMPOFF relocation.
Sizes/Widths
A size or width expression is an absolute immediate that encodes a size (in bytes) or a width (in bits).
A BITW operand is a 5-bit unsigned absolute immediate that can take on any value between 1 and 32. 32 is encoded as 0. As a special case, the following synthetic constants are defined for BITW operands with the following values:
byte: 8half: 16word: 32.
A BYTESZ operand is a 2-bit immediate with a special encoding of lg(sz) where sz is the real size in bytes. The value must be a power of 2 less than 8. The same synthetic constants are defined above to be 1, 2, and 4 respectively.
Condition Code
Condition Codes appear only in mnemonics, and use the following 1 or 2 character short forms:
| Short Form | Condition Name | Number | Canonical |
|---|---|---|---|
NV | Never | 0 | Yes |
C | Carry | 1 | Yes |
B | Below | 1 | No |
Z | Zero | 2 | Yes |
EQ | Equal | 2 | No |
V | Overflow | 3 | Yes |
O | Overflow | 3 | No |
CE | Carry/Equal | 4 | Yes |
BE | Below or Equal | 4 | No |
LT | Less | 5 | Yes |
LE | Less or Equal | 6 | Yes |
N | Negative | 7 | Yes |
S | Signed | 7 | No |
P | Positive | 8 | Yes |
NS | Not Signed | 8 | No |
GT | Greater Than | 9 | Yes |
NLE | Not Less or Equal | 9 | No |
GE | Greater or Equal | 10 | Yes |
NLT | Not Less | 10 | No |
A | Above | 11 | Yes |
NBE | Not Below or Equal | 11 | No |
NCE | Not Carry or Equal | 11 | No |
NV | Not Overflow | 12 | Yes |
NO | Not Overflow | 12 | No |
NZ | Not Zero | 13 | Yes |
NE | Not Equal | 13 | No |
NC | Not Carry | 14 | Yes |
NB | Not Below | 14 | No |
AE | Above or Equal | 14 | No |
AL | Always | 15 | Yes |
Instruction Syntax
The following charts describes how assemblers should interpret and assemble given instruction syntax forms and mnemonics.
Each Chart has the following information:
- Mnemonic: The name of the instruction, which should be interpreted case-insentively. The special variables
<c>and<x>may be written here.cis as if definedCC <c>andxis as if definedABSIMM2 <x>. - Operands: A list of operands written as the Short ID followed by a variable in
<>(e.g.GPR <d>) - Opcode: The Opcode of the instruction. This may reference the special variable
xif defined in the Mnemonic. - Special Payload Encoding: A list of variable assignments of the form
<var>=<val>wherevaris an encoding variable defined for the opcode in the ISA Spec, andvalis either an integer expression or a variable. Implicitly the name of each encoding variable that is defined as a syntax variable in the Mnemonic or the Operands list is assigned to the value of that syntax variable. The special encoding variablePrefers to the entire 24-bit payload (where its contents are undefined/ignored) - Canonical: Describes whether or not the instruction specification is canonical Canonical Specifications are the primary (or only) way to describe a particular encoding (without a
.instrdirective). Non-canonical encodings may describe a more efficient way to write or read a particular encoding, or may be useful in niche circumstances. Disassemblers and machine-code generators (such as assembly printing from a compiler) should prefer the canonical specification if it has no context otherwise.
UND
| Mnemonic | Operands | Opcode | Special Payload Encoding | Canonical |
|---|---|---|---|---|
UND | - | 0x00 | P=0 | Yes |
PAUSE
| Mnemonic | Operands | Opcode | Special Payload Encoding | Canonical |
|---|---|---|---|---|
PAUSE | ABSIMM6 <k> | 0x01 | N/A | Yes |
NOP | - | 0x01 | k=0 | No |
MOV
| Mnemonic | Operands | Opcode | Special Payload Encoding | Canonical |
|---|---|---|---|---|
MOV<c> | GPR <d>, GPR <s> | 0x02 | m=0, r=0, l=0 | Yes |
MOV<c> | GPR <d>, ANYREG <s> | 0x02 | m=MAP(s), r=0, l=0 | Yes |
MOV<c> | ANYREG <d>, GPR <s> | 0x02 | m=MAP(d), r=1, l=0 | Yes |
MOV | GPR <d>, GPR <s> | 0x02 | m=0, r=0, l=0, c=15 | No |
MOV | GPR <d>, ANYREG <s> | 0x02 | m=MAP(s), r=0, l=0, c=15 | No |
MOV | ANYREG <d>, GPR <s> | 0x02 | m=MAP(d), r=1, l=0, c=15 | No |
MOVL<c> | GPR <d>, GPR <s> | 0x02 | m=0, r=0, l=1 | Yes |
MOVL<c> | GPR <d>, ANYREG <s> | 0x02 | m=MAP(s), r=0, l=1 | Yes |
MOVL<c> | ANYREG <d>, GPR <s> | 0x02 | m=MAP(d), r=1, l=1 | Yes |
LD/ST
| Mnemonic | Operands | Opcode | Special Payload Encoding | Canonical |
|---|---|---|---|---|
LD | GPR <d>, GPR <s>, BYTESZ <w> | 0x03 | p=0 | Yes |
ST | GPR <d>, GPR <s>, BYTESZ <w> | 0x04 | p=0 | Yes |
LD | GPR <d>, GPR <s> | 0x03 | p=0,w=4 | No |
ST | GPR <d>, GPR <s> | 0x04 | p=0,w=4 | No |
PUSH | GPR <d>, GPR <s>, BYTESZ <w> | 0x04 | p=1 | Yes |
POP | GPR <d>, GPR <s>, BYTESZ <w> | 0x03 | p=1 | Yes |
PUSH | GPR <d>, GPR <s> | 0x04 | p=1,w=4 | No |
POP | GPR <d>, GPR <s> | 0x03 | p=1,w=4 | No |
PUSH | GPR <s> | 0x04 | p=1,w=4,d=30 | No |
POP | GPR <d> | 0x03 | p=1,w=4,d=30 | No |
ADDI
| Mnemonic | Operands | Opcode | Special Payload Encoding | Canonical |
|---|---|---|---|---|
ADDI | GPR <d>, SIMM16 <s> | 0x08 |