# ASAP32 ISA, a KISS inspired architecture As Simple As Possible ## General Instruction Format X = HEX B = BIN d = don't care MAX INSTRUCTIIONS = 256 ALL INSTRUCTIONS ARE ATOMIC -- maybe... ### C-Type, Control XX X X XXXX Opcode d RS1 IMM ### I-Type, Immediate XX X X XXXX Opcode RD RS1 IMM ### R-Type, Arithmetic XX X X X XXX Opcode RD RS1 RS2 Offset (Load/Store Only) ### JR-Type, Compare and Jump XX X X X XXX Opcode Jump Condition RS1 RS2 ddd ### JI-Type, Compare and Jump XX X X XXXX Opcode Jump Condition RS1 IMM ## Registers Maximum registers = 16 Register width = 32 Register 0X is always zero and read only (HW enforced) Register IP cannot be directly writen to (HW enforced) System mode: Registers AX - POG R/W, except IP (Read only) User mode: Registers AX - HX R/W, SP & CS0 R/W, others Read only ZX Always Zero AX GP-0 BX GP-1 CX GP-2 DX GP-3 EX GP-4 FX GP-5 GX GP-6 HX GP-7 IP Instruction Pointer SP Stack Pointer FLG Processor Flags CS0 Control status 0 (saves IP) CS1 Control status 1 (saves SP) CS2 Control status 2 (saves FLG) POG Page Offset & Guard, lower 16 bits -> page offset, upper 16 bits -> guard ### FLG Flag Register Bitfield The lower half is read/write The upper half can be read or written to in supervisor mode only FLG[0] Carry FLG[1] Overflow FLG[2] Zero FLG[3] Sign FLG[4-15] RESERVED FLG[16] Interrupt enable FLG[17] User mode FLG[18] Paging enabled FLG[19] Stop system clock (total shutdown if interupts are disabled) FLG[20-31] RESERVED* ## Integer Instructions ### R-Type ADD RD, RS1, RS2 RD = RS1 + RS2 ADDC RD, RS1, RS2 RD = RS1 + RS2 + FLG[0] SUB RD, RS1, RS2 RD = RS1 - RS2 SUBC RD, RS1, RS2 RD = RS1 - RS2 - FLG[0] XOR RD, RS1, RS2 RD = RS1 ^ RS2 OR RD, RS1, RS2 RD = RS1 | RS2 AND RD, RS1, RS2 RD = RS1 & RS2 LSL RD, RS1, RS2 RD = RS1 << RS2 (logical) LSR RD, RS1, RS2 RD = RS1 >> RS2 (logical) ASR RD, RS1, RS2 RD = RS1 >> RS2 MUL RD, RS1, RS2 RD = RS1 * RS2 MULU RD, RS1, RS2 RD = RS1 * RS2 (unsigned) *DIV RD, RS1, RS2 RD = RS1 / RS2 *DIVU RD, RS1, RS2 RD = RS1 / RS2 (unsigned) LDW RD, RS1, offset RD = MEM[RS1 + offset] LDWR RD, RS1, RS2 RD = MEM[RS1 + RS2] STW RD, RS1, RS2, offset MEM[RS1 + offset] = RS2 LDB RD, RS1, offset RD = MEM[RS1 + offset] & 0xFF LDBR RD, RS1, RS2 RD = MEM[RS1 + RS2] & 0xFF STB RD, RS1, RS2, offset MEM[RS1 + offset] = RS2 & 0xFF ^ Do you think load and store byte are neccary? *DIV is based on shift-and-multiply algorithm *DIV Ex: 8000/192 (8000/64)/3 (8000>>6)/3 (8000>>6)*0x5555>>16=41 ^ it may be better just to make a slow div in hw, because it will be faster than a slow div in software - I think ### I-Type ADDI RD, RS, IMM RD = RS + IMM ADDIC RD, RS, IMM RD = RS + IMM + FLG[0] SUBI RD, RS, IMM RD = RS - IMM SUBIC RD, RS, IMM RD = RS - IMM - FLG[0] XORI RD, RS, IMM RD = RS ^ IMM ORI RD, RS, IMM RD = RS | IMM ANDI RD, RS, IMM RD = RS & IMM LSLI RD, RS, IMM RD = RS << IMM (logical) LSRI RD, RS, IMM RD = RS >> IMM (logical) ASRI RD, RS, IMM RD = RS >> IMM MULI RD, RS, IMM RD = RS * IMM MULIU RD, RS, IMM RD = RS * IMM (unsigned) DIVI RD, RS, IMM RD = RS / IMM DIVIU RD, RS, IMM RD = RS / IMM (unsigned) ### JR Instructions Compare and then jump (IP = JMP) if true JMP 0 if (True) JMP 1 if (RS1 == RS2) JMP 2 if (RS1 != RS2) JMP 3 if (RS1 > RS2) Unsigned JMP 4 if (RS1 >= RS2) Unsigned JMP 5 if (RS1 > RS2) Signed JMP 6 if (RS1 >= RS2) Signed ### JI Instructions Compare and then jump (IP = JMP) if true JMPI 0 if (True) JMPI 1 if (RS1 == IMM) JMPI 2 if (RS1 != IMM) JMPI 3 if (RS1 > IMM) Unsigned JMPI 4 if (RS1 >= IMM) Unsigned JMPI 5 if (RS1 > IMM) Signed JMPI 6 if (RS1 >= IMM) Signed ### Jump Aliases These instructions do not have op codes, the rely on the assembler to convert them to the correct instruction(s) JEQ Jump if equal JLT Jump if less than JGT Jump if greater than JLE Jump if less than or equal JGE Jump if greater than or equal JLTU Jump if less than (unsigned) JGTU Jump if greater than (unsigned) JLEU Jump if less than or equal (unsigned) JGEU Jump if greater than or equal (unsigned) ### Control Instructions NOP Do nothing -> opcode = ZERO INVP* IMM Invalidate entry in TLB -- what does this do? Is it needed? CALL CS0=IP; IP=CS0 SCALL Same as INT but is used to make calls to the kernel (fixed IDT address), can be used in user mode INT* IMM CS0=IP; CS1=SP; CS2=FLG; IP=IDT[IMM]; SP=CS1; FLG[16]=0; FLG[17]=0; IRET* IP=CS0; SP=CS1; FLG=CS2; *Requires processor to be in supervisor mode (FLG[17]=0) ### Control Alias instructions These instructions do not have op codes, they rely on the assembler to convert them to the correct instruction(s) HLT* FLG[16]=0; FLG[19]=1; Spinlock the CPU, total shutdown, only reset can restart SLP* FLG[16]=1; FLG[19]=1; sleep until interrupt, pauses the cpu clock till interupt SIF* Set interrupt flag CIF* Clear interrupt flag RET IP = CS0, this is implemented using jmp or call instruction assembler controls stack PUSHR RS SP+=1 ;*SP = RS POPR RS RS = *SP ;SP-=1 PUSHI IMM SP+=1 ;*SP = IMM *Requires processor to be in supervisor mode (FLG[17]=0) ## Interrupt Descriptor Table This will be in a fixed memory location, this will contain pointers to the interupt function. IDT[0] Divide-by-zero exception IDT[1] Hardware error (NMI) IDT[2] Overflow IDT[3] Invalid Opcode IDT[4] General-protection fault IDT[5] Page fault IDT[6] Software interrupt (reserved for OS) IDT[7-31] RESERVED IDT[32-255] Platform interrupts (PIC, hard drive, keyboard, etc.) ## Page List TODO: explain page list & sliding window