User Tools

Site Tools


notes:comporg:spring2025:virconref

This is an old revision of the document!


Vircon32 ASM Reference Guide

This document is based on Vircon32 DevTools v25.1.19; older versions will contain inconsistencies.

Token Value
VirconVersion 1
VirconRevision 0
FramesPerSecond 60
CyclesPerSecond 15000000
CyclesPerFrame CyclesPerSecond / FramesPerSecond
ScreenWidth 640
ScreenHeight 360
ScreenPixels ScreenWidth * ScreenHeight
GPUTextureSize 1024×1024
GPUMaximumCartridgeTextures 256
GPURegionsPerTexture 4096
GPUPixelCapacityPerFrame 9 * ScreenPixels
GPUClearScreenPenalty -0.50f
GPUScalingPenalty +0.15f
GPURotationPenalty +0.25f
SPUMaximumCartridgeSounds 1024
SPUMaximumCartridgeSamples 1024 * 1024 * 256
SPUMaximumBiosSamples 1024 * 1024 * 1
SPUSoundChannels 16
SPUSamplingRate 44100
SPUSamplesPerFrame SPUSamplingRate / FramesPerSecond
MaximumCartridgeProgramROM 1024 * 1024 * 128
MaximumBiosProgramROM 1024 * 1024 * 1
RAMSize 1024 * 1024 * 4
MemoryCardSize 1024 * 256
MemoryBusSlaves 4
ControlBusSlaves 8
GamepadPorts 4

Assembler Data Directives (ROM)

keyword description
integer specify one or more integers
float specify one or more floats
string specify string sequence(s?)
pointer specify pointer(s?)
datafile specify datafile(s?)

Use commas to separate values (create “array” of values)

Vircon32 Instruction Set

control branch compare data convert logic int arithmetic float arithmetic float math
HLT JMP IEQ MOV CIF NOT IADD FADD FLR
WAIT CALL INE LEA CFI AND ISUB FSUB CEIL
RET IGT PUSH CIB OR IMUL FMUL ROUND
JT IGE POP CFB XOR IDIV FDIV SIN
JF ILT IN BNOT IMOD FMOD ACOS
ILE OUT SHL ISGN FSGN ATAN2
FEQ MOVS IMIN FMIN LOG
FNE SETS IMAX FMAX POW
FGT CMPS IABS FABS
FGE
FLT
FLE

Detailed View

There are 64 CPU opcodes, so instructions encode them in 6 bits. No invalid opcodes can exist. HLT is opcode 0 for safety: if an empty or invalid instruction is found, the CPU will stop execution.

opcode mneumonic category parameters description
0x00 HLT control 0 halt processing
0x01 WAIT control 0 pause processing, wait for next frame
0x02 JMP branch 1 unconditional jump to address
0x03 CALL branch 1 call subroutine
0x04 RET branch 0 return from subroutine
0x05 JT branch 2 jump if true (1)
0x06 JF branch 2 jump if false (0)
0x07 IEQ compare 2 integer equal
0x08 INE compare 2 integer not equal
0x09 IGT compare 2 integer greater than
0x0A IGE compare 2 integer greater than or equal
0x0B ILT compare 2 integer less than
0x0C ILE compare 2 integer less than or equal
0x0D FEQ compare 2 float equal
0x0E FNE compare 2 float not equal
0x0F FGT compare 2 float greater than
0x10 FGE compare 2 float greater than or equal
0x11 FLT compare 2 float less than
0x12 FLE compare 2 float less than or equal
0x13 MOV data 2 copy data
0x14 LEA data 2 load effective address
0x15 PUSH data 2 push data to stack
0x16 POP data 2 pop data from stack
0x17 IN data 2 read data in from port
0x18 OUT data 2 write data out to port
0x19 MOVS data 0 move string
0x1A SETS data 0 set string
0x1B CMPS data 1 compare string
0x1C CIF convert 1 convert integer to float
0x1D CFI convert 1 convert float to integer
0x1E CIB convert 1 convert integer to boolean
0x1F CFB convert 1 convert float to boolean
0x20 NOT logic 1 perform bitwise NOT
0x21 AND logic 2 perform bitwise AND
0x22 OR logic 2 perform bitwise iOR
0x23 XOR logic 2 perform bitwise XOR
0x24 BNOT logic 1 perform boolean NOT
0x25 SHL logic 2 perform left shift
0x26 IADD arithmetic 2 perform integer addition
0x27 ISUB arithmetic 2 perform integer subtraction
0x28 IMUL arithmetic 2 perform integer multiplication
0x29 IDIV arithmetic 2 perform integer division
0x2A IMOD arithmetic 2 perform integer modulus
0x2B ISGN arithmetic 1 perform integer sign toggle
0x2C IMIN arithmetic 2 perform integer minimum
0x2D IMAX arithmetic 2 perform integer maximum
0x2E IABS arithmetic 1 perform integer absolute value
0x2F FADD arithmetic 2 perform float addition
0x30 FSUB arithmetic 2 perform float subtraction
0x31 FMUL arithmetic 2 perform float multiplication
0x32 FDIV arithmetic 2 perform float division
0x33 FMOD arithmetic 2 perform float modulus
0x34 FSGN arithmetic 1 perform float sign toggle
0x35 FMIN arithmetic 2 perform float minimum
0x36 FMAX arithmetic 2 perform float maximum
0x37 FABS arithmetic 1 perform float absolute value
0x38 FLR math 1 perform float floor operation
0x39 CEIL math 1 perform float ceiling operation
0x3A ROUND math 1 perform float rounding operation
0x3B SIN math 1 perform float sine operation
0x3C ACOS math 1 perform float arc cosine operation
0x3D ATAN2 math 2 perform float arc tangent operation
0x3E LOG math 1 perform float natural logarithm operation
0x3F POW math 2 perform float power operation

Vircon32 Memory Map

Name Address/Range Description
RAMFirstAddress 0x00000000-0x003FFFFF read/write memory (16MB)
stack init address 0x003FFFFF default location of SP (last RAM address)
BiosProgramROMFirstAddress 0x10000000 Vircon32 BIOS
BIOS error handler address 0x10000000 start of error handler logic
BIOS program start address 0x10000004 start of BIOS main logic
CartridgeProgramROMFirstAddress 0x20000000 Cartridge Data
MemoryCardRAMFirstAddress 0x30000000 Memory Card Data

Vircon32 I/O Port Layout

Port Address Vircon32 ID Description
0x000 TIM_FirstPort time related functionality
0x100 RNG_FirstPort random number generator
0x200 GPU_FirstPort graphics
0x300 SPU_FirstPort sound processing
0x400 INP_FirstPort input (game controllers)
0x500 CAR_FirstPort cartridge interface
0x600 MEM_FirstPort memory card

IOPorts

TIME

Type Port Name Description
IN 0x000 TIM_CurrentDate retrieve current date
IN 0x001 TIM_CurrentTime retrieve current time
IN 0x002 TIM_FrameCounter retrieve current frame count
IN 0x003 TIM_CycleCounter retrieve current cycle count

example: get current frame count

    in R0,  TIM_FrameCounter    ; load current frame count into R0

RNG

Type Port Name Description
IN 0x100 RNG_CurrentValue obtain pseudorandom value
OUT 0x100 RNG_CurrentValue Seed random number generator

GPU

Type Port Name Description
OUT 0x200 GPU_Command perform GPU operation
??? 0x201 GPU_RemainingPixels ???
OUT 0x202 GPU_ClearColor color to clear the screen with
??? 0x203 GPU_MultiplyColor ???
??? 0x204 GPU_ActiveBlending ???
IN 0x204 GPU_SelectedTexture obtain current selected texture
OUT 0x204 GPU_SelectedTexture texture ID to select (-1 for BIOS)
IN 0x205 GPU_SelectedRegion obtain current selected region
OUT 0x205 GPU_SelectedRegion region ID to select
OUT 0x206 GPU_DrawingPointX set X position to draw selected region
OUT 0x207 GPU_DrawingPointY set Y position to draw selected region
??? 0x208 GPU_DrawingScaleX sets X scaling with a float as input
??? 0x209 GPU_DrawingScaleY sets Y scaling with a float as input
??? 0x20A GPU_DrawingAngle ???
OUT 0x20B GPU_RegionMinX set Min X coordinate for region
OUT 0x20C GPU_RegionMinY set Min Y coordinate for region
OUT 0x20D GPU_RegionMaxX set Max X coordinate for region
OUT 0x20E GPU_RegionMaxY set Max Y coordinate for region
OUT 0x20F GPU_RegionHotspotX set region Hotspot X coordinate
OUT 0x210 GPU_RegionHotspotY set region Hotspot Y coordinate

Commands that can be issued to the GPU:

value name description
0x10 GPUCommand_ClearScreen clears the screen using current clear color
0x11 GPUCommand_DrawRegion draws the selected region: Rotation off, Zoom off
0x12 GPUCommand_DrawRegionZoomed draws the selected region: Rotation off, Zoom on
0x13 GPUCommand_DrawRegionRotated draws the selected region: Rotation on , Zoom off
0x14 GPUCommand_DrawRegionRotozoomed draws the selected region: Rotation on , Zoom on

GPU Active Blending Port Commands

Active blending:

value name description
0x20 GPUBlendingMode_Alpha default rendering, uses alpha channel as transparency
0x21 GPUBlendingMode_Add colors are added (light effect), also called linear dodge
0x22 GPUBlendingMode_Subtract colors are subtracted (shadow effect), also called difference

SPU

Type Port Name Description
??? 0x300 SPU_Command ???
??? 0x301 SPU_GlobalVolume ???
OUT 0x302 SPU_SelectedSound ???
OUT 0x303 SPU_SelectedChannel ???
??? 0x304 SPU_SoundLength ???
??? 0x305 SPU_SoundPlayWithLoop ???
??? 0x306 SPU_SoundLoopStart ???
??? 0x307 SPU_SoundLoopEnd ???
??? 0x308 SPU_ChannelState ???
??? 0x309 SPU_ChannelAssignedSound ???
??? 0x30A SPU_ChannelVolume ???
??? 0x30B SPU_ChannelSpeed ???
??? 0x30C SPU_ChannelLoopEnabled ???
??? 0x30D SPU_ChannelPosition ???

SPU Commands

Commands for the SPU:

value name description
0x30 SPUCommand_PlaySelectedChannel if paused, it is resumed; if already playing, it is retriggered
0x31 SPUCommand_PauseSelectedChannel no effect if the channel was not playing
0x32 SPUCommand_StopSelectedChannel position is rewinded to sound start
0x33 SPUCommand_PauseAllChannels same as applying PauseChannel to all channels
0x34 SPUCommand_ResumeAllChannels same as applying PlayChannel to all paused channels
0x35 SPUCommand_StopAllChannels same as applying StopChannel to all channels

SPU Channel States

States of the sound channels:

value name description
0x40 SPUChannelState_Stopped channel is not playing, and will begin new reproduction on play
0x41 SPUChannelState_Paused channel is paused, and will resume reproduction on play
0x42 SPUChannelState_Playing channel is currently playing, until its assigned sound ends

INPUT

Type Port Name Description
IN 0x400 INP_SelectedGamepad Which gamepad is selected (0-3)
OUT 0x400 INP_SelectedGamepad Select indicated gamepad (0-3)
??? 0x401 INP_GamepadConnected ???
IN 0x402 INP_GamepadLeft Left Key input
IN 0x403 INP_GamepadRight Right Key input
IN 0x404 INP_GamepadUp Up key input
IN 0x405 INP_GamepadDown Down key input
IN 0x406 INP_GamepadButtonStart Enter key input
IN 0x407 INP_GamepadButtonA X key input
IN 0x408 INP_GamepadButtonB Z key input
IN 0x409 INP_GamepadButtonX S key input
IN 0x40A INP_GamepadButtonY A key input
IN 0x40B INP_GamepadButtonL Q key input
IN 0x40C INP_GamepadButtonR W key input
Type Port Name Description
IN? 0x500 CAR_Connected status of cartridge being connected
IN? 0x501 CAR_ProgramROMSize size of program ROM
IN? 0x502 CAR_NumberOfTextures number of cartridge textures
IN? 0x503 CAR_NumberOfSounds number of cartridge sounds

MEMCARD

Type Port Name Description
IN? 0x600 MEM_Connected status of memory card being connected

Instruction Format

  • bits 31-26: opcode
  • bit 25: immediate value
  • bits 24-21: register 1
  • bits 20-17: register 2
  • bits 16-14: address mode
  • bits 13-0: port number

If the immediate value bit is set, an additional word is read to be used as a parameter to the instruction.

HLT

WAIT

JMP

Unconditional jump. Forcibly redirect program flow to indicated address. The address is somewhere else in the program logic, likely identified by some set label.

Structure and variants

  • Variant 1:
    JMP { ImmediateValue }
  • Variant 2:
    JMP { Register1 }

Processing actions

  • Variant 1:
    InstructionPointer = ImmediateValue
  • Variant 2:
    InstructionPointer = Register1

Description

JMP performs an unconditional jump to the address specified by its operand. After processing this instruction the CPU will continue execution at the new address.

Examples

Jumping to a label (memory address/offset):

    jmp _label
    ...
_label:

Jumping to address stored in register:

    jmp R0

CALL

RET

JT

Jump if True: a conditional jump typically used following a comparison instruction, should the queried register contain a true (1) value, jump to indicated address.

NOTE

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

Structure and variants

  • Variant 1:
    JT { Register1 }, { ImmediateValue }
  • Variant 2:
    JT { Register1 }, { Register2 }

Effect

  • Variant 1:
    if Register1 != 0 then InstructionPointer = ImmediateValue
  • Variant 2:
    if Register1 != 0 then InstructionPointer = Register2

Description

JT performs a jump only if its first operand is true, i.e. non zero when taken as an integer. In that case its behavior is the same as an unconditional jump. Otherwise it has no effect.

JF

Jump if False: a conditional jump typically used following a comparison instruction, should the queried register contain a false (0) value, jump to indicated address.

NOTE

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

Structure and variants

  • Variant 1:
    JF { Register1 }, { ImmediateValue }
  • Variant 2:
    JF { Register1 }, { Register2 }

Effect

  • Variant 1:
    if Register1 == 0 then InstructionPointer = ImmediateValue
  • Variant 2:
    if Register1 == 0 then InstructionPointer = Register2

Description

JF performs a jump only if its first operand is false, i.e. zero when taken as an integer. In that case its behavior is the same as an unconditional jump. Otherwise it has no effect.

Integer Comparisons

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

There are six relational operations:

  • is equal to
  • is not equal to
  • is less than
  • is than or equal to
  • is greater than
  • is greater than or equal to

IEQ

Integer Compare Equality: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

Should the first operand contain the same information as the second operand, the result will be true. Otherwise, false.

Structure and variants

  • Variant 1:
    IEQ { Register1 }, { ImmediateValue }
  • Variant 2:
    IEQ { Register1 }, { Register2 }

Processing actions

  • Variant 1:
    if Register1 == ImmediateValue then Register1 = 1 else Register1 = 0
  • Variant 2:
    if Register1 == Register2 then Register1 = 1 else Register1 = 0

Description

IEQ takes two operands interpreted as integers, and checks if they are equal. It will store the boolean result in the first operand, which is always a register.

INE

Integer Not Equal: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

Here, we test to see if the first operand is not equal to the second operand. If they are equal, the result is false, otherwise, not being equal yields a result of true.

Structure and variants

  • Variant 1:
    INE { Register1 }, { ImmediateValue }
  • Variant 2:
    INE { Register1 }, { Register2 }

Processing actions

  • Variant 1:
    if Register1 != ImmediateValue then Register1 = 1 else Register1 = 0
  • Variant 2:
    if Register1 != Register2 then Register1 = 1 else Register1 = 0

Description

INE takes two operands interpreted as integers, and checks if they are different. It will store the boolean result in the first operand, which is always a register.

IGT

Integer Greater Than: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

In this case, we are testing if the first operand is greater than the second operand.

Structure and variants

  • Variant 1:
    IGT { Register1 }, { ImmediateValue }
  • Variant 2:
    IGT { Register1 }, { Register2 }

Processing actions

  • Variant 1:
    if Register1 > ImmediateValue then Register1 = 1 else Register1 = 0
  • Variant 2:
    if Register1 > Register2 then Register1 = 1 else Register1 = 0

Description

IGT takes two operands interpreted as integers, and checks if the first one is greater than the second. It will store the boolean result in the first operand, which is always a register.

IGE

Integer Greater Than Or Equal: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

In this case, we are testing if the first operand is greater than or equal to the second operand.

NOTE

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

There are six relational operations:

  • is equal to
  • is not equal to
  • is less than
  • is than or equal to
  • is greater than
  • is greater than or equal to

Structure and variants

  • Variant 1:
    IGE { Register1 }, { ImmediateValue }
  • Variant 2:
    IGE { Register1 }, { Register2 }

Processing actions

  • Variant 1:
    if Register1 >= ImmediateValue then Register1 = 1 else Register1 = 0
  • Variant 2:
    if Register1 >= Register2 then Register1 = 1 else Register1 = 0

Description

IGE takes two operands interpreted as integers, and checks if the first one is greater or equal to the second. It will store the boolean result in the first operand, which is always a register.

ILT

Integer Less Than: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

In this case, we are testing if the first operand is less than the second operand.

NOTE

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

There are six relational operations:

  • is equal to
  • is not equal to
  • is less than
  • is than or equal to
  • is greater than
  • is greater than or equal to

Structure and variants

  • Variant 1:
    ILT { Register1 }, { ImmediateValue }
  • Variant 2:
    ILT { Register1 }, { Register2 }

Processing actions

  • Variant 1:
    if Register1 < ImmediateValue then Register1 = 1 else Register1 = 0
  • Variant 2:
    if Register1 < Register2 then Register1 = 1 else Register1 = 0

Description

ILT takes two operands interpreted as integers, and checks if the first one is less than the second. It will store the boolean result in the first operand, which is always a register.

ILE

Integer Less Than Or Equal: comparisons allow us typically to evaluate two values, in accordance with some relational operation, resulting in a true (1) or false (0) result.

In this case, we are testing if the first operand is less than or equal to the second operand.

NOTE

For the purposes of comparisons and conditional jumps on Vircon32:

  • true is 1 (technically non-zero)
  • false is 0

There are six relational operations:

  • is equal to
  • is not equal to
  • is less than
  • is than or equal to
  • is greater than
  • is greater than or equal to

Structure and variants

Variant Form Action
1
ILE DSTREG, ImmediateValue
if (DSTREG <= ImmediateValue)
    DSTREG=1;
else
    DSTREG=0;
2
ILE DSTREG, SRCREG
if (DSTREG <= SRCREG)
    DSTREG=1;
else
    DSTREG=0;

Description

ILE takes two operands interpreted as integers, and checks if the first one is less or equal to the second. It will store the boolean result in the first operand, which is always a register.

FEQ

FNE

FGT

FGE

FLT

FLE

MOV

MOVE: your general purpose data-copying instruction.

Addressing

MOVE, like other data-centric instructions, makes use of various addressing modes:

  • register: source/destination is an inbuilt CPU register
  • immediate: some literal constant (be it data or a memory address)
  • indirect: value isn't the data, but a memory address to where the data is. Think pointer dereference. It comes in 3 varieties:
  • indexed: an offset to some existing piece of data.
    • immediate: a literal constant (data or memory address)
    • indexed: used with immediate/register, but we can do additional math to get an offset from the address. Think pointer dereference on an array.
    • register: a CPU register

Indirect processing is accomplished with the [ ] (square brackets) surrounding the value we wish to dereference (we're not interested in the direct thing, but indirectly in what that thing contains).

Structure and variants

Variant Form Action
1
MOV DSTREG, ImmediateValue
DSTREG = ImmediateValue;
2
MOV DSTREG, SRCREG
DSTREG = SRCREG;
3
MOV DSTREG, [ImmediateValue]
DSTREG = Memory[ImmediateValue];
4
MOV DSTREG, [SRCREG]
DSTREG = Memory[SRCREG];
5
MOV DSTREG, [SRCREG+ImmediateValue]
DSTREG = Memory[SRCREG+ImmediateValue];
6
MOV [ImmediateValue], SRCREG
Memory[ImmediateValue] = SRCREG;
7
MOV [DSTREG], SRCREG
Memory[DSTREG] = SRCREG;
8
MOV [DSTREG+ImmediateValue], SRCREG
Memory[DSTREG+ImmediateValue] = SRCREG;

Description

MOV copies the value indicated in its second operand into the register or memory address indicated by its first operand. MOV is the most complex instruction to process because it needs to distinguish between 8 different addressing modes.

The instruction specifies which of the 8 modes to use in its “Addressing mode” field, being the possible values interpreted as follows:

MOV Addressing modes
Binary Destination Source
000 DSTREG Immediate Value
001 DSTREG SRCREG
010 DSTREG Memory [Immediate Value]
011 DSTREG Memory [SRCREG]
100 DSTREG Memory [SRCREG + Immediate Value]
101 Memory[Immediate Value] SRCREG
110 Memory[DSTREG] SRCREG
111 Memory[DSTREG + Immediate Value] SRCREG

LEA

Load Effective Address of a memory position.

Addressing

LEA, like other data-centric instructions, makes use of various addressing modes:

  • register: source/destination is an inbuilt CPU register
  • immediate: some literal constant (be it data or a memory address)
  • indirect: value isn't the data, but a memory address to where the data is. Think pointer dereference. It comes in 3 varieties:
  • indexed: an offset to some existing piece of data.
    • immediate: a literal constant (data or memory address)
    • indexed: used with immediate/register, but we can do additional math to get an offset from the address. Think pointer dereference on an array.
    • register: a CPU register

Indirect processing is accomplished with the [ ] (square brackets) surrounding the value we wish to dereference (we're not interested in the direct thing, but indirectly in what that thing contains).

Structure and variants

  • Variant 1:
    LEA { Register1 }, [ { Register2 } ]
  • Variant 2:
    LEA { Register1 }, [ { Register2 } + { ImmediateValue } ]

Processing actions

  • Register:
    Register1 = Register2
  • Indexed:
    Register1 = Register2 + ImmediateValue

Description

LEA takes a memory address as second operand. It stores that address (not its contents) into the register given as first operand. The most useful case is when the address is given in the form pointer + offset, since the addition is automatically performed.

PUSH

Save to top of stack

Structure and variants

  • PUSH { Register1 }

Processing actions

  • Stack.Push(Register1)

Description

PUSH uses the CPU hardware stack to add the value contained in the given register at the top of the stack. When you PUSH a value onto the stack, the STACK POINTER (SP) is adjusted downward by one address offset (stack grows down).

POP

Load from top of stack

Structure and variants

  • POP { Register1 }

Processing actions

  • Register1 = Stack.Pop()

Description

POP uses the CPU hardware stack to remove a value from the top of the stack and write it in the given register. When you POP a value off the stack, the STACK POINTER (SP) is adjusted upward by one address offset (stack grows down, shrinks up).

IN

Receive input from an I/O port

Structure and variants

  • IN {Register1}, {PortNumber}

Processing actions

  • Register1 = Port[ PortNumber ]

Description

In uses the control bus to read from an I/O port in another chip and stores the returned value in the specified register. This read request may lead to side effects depending on the specified port.

OUT

Write to an I/O port

Structure and variants

  • OUT {PortNumber}, [{ImmediateValue}]
  • OUT {PortNumber}, {Register1}

Processing actions

  • Port[PortNumber] = ImmediateValue
  • Port[PortNumber] = Register1

Description

OUT uses the control bus to write the specified value to an I/O port in another chip. This write request may lead to side effects depending on the specified port

MOVS

Copy string (HW memcpy)

Structure and variants

  • MOVS

Processing actions

  • Memory[ DR ] = Memory[ SR ]
  • DR += 1
  • SR += 1
  • CR -= 1
  • if CR > 0 then InstructionPointer -= 1

Description

MOVS copies a value from the memory address pointed by SR to the one pointed by DR (as in a supposed MOV [DR], [SR]). It then implements a local loop to repeat itself until the counter in CR reaches 0, while working on consecutive addresses. Note that even when called with a value of CR of zero or less, MOVS will always perform the described loop at least once. This instruction is the only way in Vircon32 CPU to directly copy values from 2 places in memory without going through a register.

SETS

Set string (HW memset)

Structure and variants

  • SETS

Processing actions

  • Memory[ DR ] = SR
  • DR += 1
  • CR -= 1
  • if CR > 0 then InstructionPointer -= 1

Description

SETS copies the value in SR to the address pointed by DR (as in a MOV [DR], SR). It then implements a local loop to repeat itself until the counter in CR reaches 0, while writing to consecutive addresses. Note that even when called with a value of CR of zero or less, SETS will always perform the described loop at least once.

CMPS

Compare string (HW memcmp)

Structure and variants

  • CMPS { Register1 }

Processing actions

  • Register1 = Memory[ DR ] – Memory[ SR ]
  • if Register1 != 0 then end processing
  • DR += 1
  • SR += 1
  • CR -= 1
  • if CR > 0 then InstructionPointer -= 1

Description

CMPS takes as a reference the compares the value in the address pointed by DR and compares it with the one pointed by SR, by subtracting. It then implements a local loop to repeat itself until the counter in CR reaches 0, while reading consecutive addresses. The comparison result will be stored in the specified register, and will be zero when equal, positive when some value at [DR] was greater, and negative when some value in [SR] was greater. Note that even when called with a value of CR of zero or less, CMPS will always perform the described loop at least once.

CIF

Convert Integer to Float

Structure and variants

Variant Form Action
1
CIF DSTREG
DSTREG = (float)DSTREG;

Description

CIF interprets the specified register as an integer value. Then converts that value to a float representation and stores the result back in the same register. Note that, due to the limited precision of the float representation, high enough values of a 32-bit integer will result in a precision loss when represented as a float.

CFI

Convert Float to Integer

Structure and variants

Variant Form Action
1
CFI DSTREG
DSTREG = (int)DSTREG;

Description

CFI interprets the specified register as a float value. Then converts that value to an integer representation and stores the result back in the same register. Conversion is not done through rounding, but instead by truncating (the fractional part is discarded). Note that, due to the much greater range of the float representation, high enough values of a float will result in a precision loss when represented as a 32-bit integer.

CIB

Convert Integer to Boolean

Structure and variants

Variant Form Action
1
CIB DSTREG
if (DSTREG != 0)
    DSTREG = 1;
else
    DSTREG = 0;

Description

CIB interprets the specified register as an integer value. Then converts that value to its standard boolean representation and stores the result back in the same register. This means that all non-zero values will be converted to 1.

CFB

Convert Float to Boolean

Structure and variants

Variant Form Action
1
CFB DSTREG
if (DSTREG != 0.0)
    DSTREG = 1;
else
    DSTREG = 0;

Description

CFB interprets the specified register as a float value. Then converts that value to either 0 (for float value 0.0), or 1 (for any other value) and stores it back in that register.

NOT

Bitwise NOT

Structure and variants

  • NOT { Register1 }

Processing actions

  • Register1 = NOT Register1

Description

NOT performs a binary ‘not’ by inverting all of the bits in the specified register.

AND

Bitwise AND

AND truth table

A B X
false false false
false true false
true false false
true true true

Structure and variants

Variant Form Action
1 AND DSTREG, ImmediateValue DSTREG = DSTREG & ImmediateValue;
2 AND DSTREG, SRCREG DSTREG = DSTREG & SRCREG;

Description

AND performs a Bitwise AND between each pair of respective bits in the 2 specified operands. The result is stored in the first of them, which is always a register.

OR

Bitwise iOR

iOR truth table

A B X
false false false
false true true
true false true
true true true

Structure and variants

Variant Form Action
1 OR DSTREG, ImmediateValue DSTREG = DSTREG | ImmediateValue;
2 OR DSTREG, SRCREG DSTREG = DSTREG | SRCREG;

Description

OR performs a Bitwise iOR between each pair of respective bits in the 2 specified operands. The result is stored in the first of them, which is always a register.

XOR

Bitwise XOR

XOR truth table

A B X
false false false
false true true
true false true
true true false

Structure and variants

Variant Form Action
1 XOR DSTREG, ImmediateValue DSTREG = DSTREG ^ ImmediateValue;
2 XOR DSTREG, SRCREG DSTREG = DSTREG ^ SRCREG;

Description

XOR performs a Bitwise EXCLUSIVE OR between each pair of respective bits in the 2 specified operands. The result is stored in the first of them, which is always a register.

BNOT

Boolean NOT

Structure and variants

  • BNOT { Register1 }

Processing actions

  • if Register1 == 0 then Register1 = 1 else Register1 = 0

Description

BNOT interprets the specified register as a boolean and then converts it to the opposite boolean value. This is equivalent to first using CIB and then inverting bit number 0.

SHL

Bit shift left

Structure and variants

  • (Variant 1): SHL { Register1 }, { ImmediateValue }
  • (Variant 2): SHL { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = Register1 << ImmediateValue
  • (Variant 2): Register1 = Register1 << Register2

Description

SHL performs an bit shift to the left in the specified register. The second operand is taken as an integer number of positions to shift. Shifting 0 positions has no effect, while negative values result in shifting right. The shift type is logical: in shifts left, overflow is discarded and zeroes are introduced as least significant bits. In shifts right, underflow is discarded and zeroes are introduced as most significant bits.

IADD

Integer Addition

Structure and variants

  • (Variant 1): IADD { Register1 }, { ImmediateValue }
  • (Variant 2): IADD { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 += ImmediateValue
  • (Variant 2): Register1 += Register2

Description

IADD interprets both of its operands as integers and performs an addition. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

ISUB

Integer Subtraction

Structure and variants

  • (Variant 1): ISUB { Register1 }, { ImmediateValue }
  • (Variant 2): ISUB { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 -= ImmediateValue
  • (Variant 2): Register1 -= Register2

Description

ISUB interprets both of its operands as integers and performs a subtraction. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

IMUL

Integer Multiplication

Structure and variants

  • (Variant 1): IMUL { Register1 }, { ImmediateValue }
  • (Variant 2): IMUL { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 *= ImmediateValue
  • (Variant 2): Register1 *= Register2

Description

IMUL interprets both of its operands as integers and performs a multiplication. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

IDIV

Integer Division

Structure and variants

  • (Variant 1): IDIV { Register1 }, { ImmediateValue }
  • (Variant 2): IDIV { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 /= ImmediateValue
  • (Variant 2): Register1 /= Register2

Description

IDIV interprets both of its operands as integers and performs a division. The result is stored in the first operand, which is always a register.

IMOD

Integer Modulus

Structure and variants

  • (Variant 1): IMOD { Register1 }, { ImmediateValue }
  • (Variant 2): IMOD { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = Register1 mod ImmediateValue
  • (Variant 2): Register1 = Register1 mod Register2

Description

IMOD interprets both of its operands as integers and performs a division. The remainder of that division is stored in the first operand, which is always a register.

ISGN

Integer Sign Change

Structure and variants

  • ISGN { Register1 }

Processing actions

  • Register1 = -Register1

Description

ISGN interprets the operand register as an integer and inverts its sign.

IMIN

Integer Minimum

Structure and variants

  • (Variant 1): IMIN { Register1 }, { ImmediateValue }
  • (Variant 2): IMIN { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = min( Register1, ImmediateValue )
  • (Variant 2): Register1 = min( Register1, Register2 )

Description

IMIN interprets both of its operands as integers. It then takes the minimum of both values and stores it in the first operand, which is always a register.

IMAX

Integer Maximum

Structure and variants

  • (Variant 1): IMAX { Register1 }, { ImmediateValue }
  • (Variant 2): IMAX { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = max( Register1, ImmediateValue )
  • (Variant 2): Register1 = max( Register1, Register2 )

Description

IMAX interprets both of its operands as integers. It then takes the maximum of both values and stores it in the first operand, which is always a register.

IABS

Integer Absolute Value

Structure and variants

  • IABS { Register1 }

Processing actions

  • Register1 = abs( Register1 )

Description

IABS interprets the operand register as an integer and takes its absolute value.

FADD

Float Addition

Structure and variants

  • (Variant 1): FADD { Register1 }, { ImmediateValue }
  • (Variant 2): FADD { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 += ImmediateValue
  • (Variant 2): Register1 += Register2

Description

FADD interprets both of its operands as floats and performs an addition. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

FSUB

Float Subtraction

Structure and variants

  • (Variant 1): FSUB { Register1 }, { ImmediateValue }
  • (Variant 2): FSUB { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 -= ImmediateValue
  • (Variant 2): Register1 -= Register2

Description

FSUB interprets both of its operands as floats and performs a subtraction. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

FMUL

Float Multiplication

Structure and variants

  • (Variant 1): FMUL { Register1 }, { ImmediateValue }
  • (Variant 2): FMUL { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 *= ImmediateValue
  • (Variant 2): Register1 *= Register2

Description

FMUL interprets both of its operands as floats and performs a multiplication. The result is stored in the first operand, which is always a register. Overflow bits are discarded.

FDIV

Float Division

Structure and variants

  • (Variant 1): FDIV { Register1 }, { ImmediateValue }
  • (Variant 2): FDIV { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 /= ImmediateValue
  • (Variant 2): Register1 /= Register2

Description

FDIV interprets both of its operands as floats and performs a division. The result is stored in the first operand, which is always a register.

FMOD

Float Modulus

Structure and variants

  • (Variant 1): FMOD { Register1 }, { ImmediateValue }
  • (Variant 2): FMOD { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = fmod(Register1, ImmediateValue)
  • (Variant 2): Register1 = fmod(Register1, Register2)

Description

FMOD interprets both of its operands as floats and performs a division. It then takes the remainder of that division when the result’s fractional part is discarded and stores it in the first operand, which is always a register.

FSGN

Float Sign Change

Structure and variants

  • FSGN { Register1 }

Processing actions

  • Register1 = -Register1

Description

FSGN interprets the operand register as a float and inverts its sign.

FMIN

Float Minimum

Structure and variants

  • (Variant 1): FMIN { Register1 }, { ImmediateValue }
  • (Variant 2): FMIN { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = min( Register1, ImmediateValue )
  • (Variant 2): Register1 = min( Register1, Register2 )

Description

FMIN interprets both of its operands as floats. It then takes the minimum of both values and stores it in the first operand, which is always a register.

FMAX

Float Maximum

Structure and variants

  • (Variant 1): FMAX { Register1 }, { ImmediateValue }
  • (Variant 2): FMAX { Register1 }, { Register2 }

Processing actions

  • (Variant 1): Register1 = max( Register1, ImmediateValue )
  • (Variant 2): Register1 = max( Register1, Register2 )

Description

FMAX interprets both of its operands as floats. It then takes the maximum of both values and stores it in the first operand, which is always a register.

FABS

Float Absolute Value

Structure and variants

  • FABS { Register1 }

Processing actions

  • Register1 = abs( Register1 )

Description

FABS interprets the operand register as a float and takes its absolute value.

FLR

Round down

Structure and variants

  • FLR { Register1 }

Processing actions

  • Register1 = floor( Register1 )

Description

FLR interprets the operand register as a float and rounds it downwards to an integer value. Note that the result is not converted to an integer, but is still a float.

CEIL

Round up

Structure and variants

  • CEIL { Register1 }

Processing actions

  • Register1 = ceil( Register1 )

Description

CEIL interprets the operand register as a float and rounds it upwards to an integer value. Note that the result is not converted to an integer, but is still a float.

ROUND

Round to nearest integer

Structure and variants

  • ROUND { Register1 }

Processing actions

  • Register1 = round( Register1 )

Description

ROUND interprets the operand register as a float and rounds it to the closest integer value. Note that the result is not converted to an integer, but is still a float.

SIN

Sine

Structure and variants

  • SIN { Register1 }

Processing actions

  • Register1 = sin( Register1 )

Description

SIN interprets the operand register as a float and calculates the sine of that value. The sine function will interpret its argument in radians.

ACOS

Arc cosine

Structure and variants

  • ACOS { Register1 }

Processing actions

  • Register1 = acos( Register1 )

Description

ACOS interprets the operand register as a float and calculates the arc cosine of that value. The result is given in radians, in the range [0, pi].

ATAN2

Arc Tangent from x and y

Structure and variants

  • ATAN2 { Register1 }, { Register2 }

Processing actions

  • Register1 = atan2( Register1, Register2 )

Description

ATAN2 interprets both operand registers as floats and calculates the angle of a vector such that Vx = Register2 and Vy = Register1. The result is stored in the first operand register and will be given in radians, in the range [-pi, pi]. The origin of angles is located at (Vx > 0, Vy = 0) and angles grow when rotating towards (Vx = 0, Vy > 0).

LOG

Natural logarithm

Structure and variants

  • LOG { Register1 }

Processing actions

  • Register1 = log( Register1 )

Description

LOG interprets the operand register as a float and calculates the logarithm base e of that value.

POW

Raise to a Power

Structure and variants

  • POW { Register1 }, { Register2 }

Processing actions

  • Register1 = pow( Register1, Register2 )

Description

POW interprets both operand registers as floats and calculates the result of raising the first operand to the power of the second operand. The result is stored in the first operand register.

To Be Done

    // -----------------------------------------------------------------------------
    
    enum class CPURegisters: int
    {
        // all 16 general-purpose registers
        Register00 = 0,
        Register01,
        Register02,
        Register03,
        Register04,
        Register05,
        Register06,
        Register07,
        Register08,
        Register09,
        Register10,
        Register11,
        Register12,
        Register13,
        Register14,
        Register15,
        
        // alternate names for specific registers
        CountRegister       = 11,
        SourceRegister      = 12,
        DestinationRegister = 13,
        BasePointer         = 14,
        StackPointer        = 15
    };
    
    // -----------------------------------------------------------------------------
    
    enum class AddressingModes : unsigned int
    {
        RegisterFromImmediate = 0,      // syntax: MOV R1, 25
        RegisterFromRegister,           // syntax: MOV R1, R2
        RegisterFromImmediateAddress,   // syntax: MOV R1, [25]
        RegisterFromRegisterAddress,    // syntax: MOV R1, [R2]
        RegisterFromAddressOffset,      // syntax: MOV R1, [R2+25]
        ImmediateAddressFromRegister,   // syntax: MOV [25], R2
        RegisterAddressFromRegister,    // syntax: MOV [R1], R2
        AddressOffsetFromRegister       // syntax: MOV [R1+25], R2
    };
    
    // -----------------------------------------------------------------------------
    
    enum class CPUErrorCodes: uint32_t
    {
        InvalidMemoryRead = 0,
        InvalidMemoryWrite,
        InvalidPortRead,
        InvalidPortWrite,
        StackOverflow,
        StackUnderflow,
        DivisionError,
        ArcCosineError,
        ArcTangent2Error,
        LogarithmError,
        PowerError
    };
}
notes/comporg/spring2025/virconref.1740673501.txt.gz · Last modified: 2025/02/27 16:25 by wedge