npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

mips32-compiler

v1.0.4

Published

A package with a method to compile C code into mips32 asm code

Downloads

85

Readme

Mips compiler

Description

This repository constitutes a Pseudo C language compiler to a valid mips32 code with 32 general purpose registers. The generated mips32 code according to this Cheat sheet with several differences. | Instruction | Operation | |-----------------|-------------------| | J address | pc = address | | NOOP | None |

The input string undergoes several transformations before being compiled into Mips32 instructions.

image.

First, the C code is passed through the AST(Abstract syntax tree) compiler which splits the code into tokens, then it is assembled into an intermediary ASM instruction set which resembles x86 instruction set with some differences, and at the end is, again translated into mips32 code.

Playground

The compiler can be tested Here

Predefined methods.

There are several predefined methods which can help in order to use this library.

int setElement(int buffer,int pos,int element);

This will set an element at a pointers position (pos << 2). Its equivalent of using buffer[pos] = element. *(buffer + pos << 2) = element;

int getElement(int buffer,int pos);

This will get an element at a pointers position (pos << 2). Its equivalent of using element = buffer[pos]. element = *(buffer + pos << 2);

int printNumber(int element);

Will put the 32 bits number on the stdout pointer position.

int printChar(int element);

Will put a char at the current stdout pointer offset (this is used to print individual ASCII characters).

Examples

Hello world

For this one, we should print all characters one after another.

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  void main() {
    printChar(72);printChar(101);
    printChar(108);printChar(108);
    printChar(111);printChar(32);
    printChar(87);printChar(111);
    printChar(114);printChar(108);
    printChar(100);
  }
`, {
  stdout: 1024 * 512,
  stackPointer: 1024 * 1024,
  memorySize: 1024 * 1024 * 4
})

mipsCompiler.compile();
mipsCompiler.run(); // This runs the mips32 instructions in order

console.log(mipsCompiler.stdoutBuffer()); // This will print "Hello World"

Sum of 2 numbers.

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  void main() {
    int a = 5;
    int b = 10;
    printNumber(a + b);
  }
`, {
  stdout: 1024 * 512, // The pointer from where "mipsCompiler.stdoutBuffer()" will transform the data into a string.
  stackPointer: 1024 * 1024, // The stack pointer for when the program will start to run.
  memorySize: 1024 * 1024 * 4 // The memory of the process that runs the program in bytes.
})

mipsCompiler.compile();
mipsCompiler.run(); // This runs the mips32 instructions in order

console.log(mipsCompiler.stdoutBuffer()); // This will print 15

Recursive fibbonaci.

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  int fibboRecursive(int n) {
    if ( n < 2 ) {
      return 1;
    }
    return fibboRecursive ( n - 1 ) + fibboRecursive ( n - 2 );
  }
  void main() {
    printNumber(fibboRecursive(8));
  }
`, {
  stdout: 1024 * 512,
  stackPointer: 1024 * 1024,
  memorySize: 1024 * 1024 * 4
})

mipsCompiler.compile();
mipsCompiler.run(); // This runs the mips32 instructions in order

console.log(mipsCompiler.stdoutBuffer()); // This will print 34

Print first 10 digits

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  void main() {
    for(int i = 0; i < 10; i = i + 1) {
      printNumber(i);
      printChar(32);
    }
  }
`, {
  stdout: 1024 * 512,
  stackPointer: 1024 * 1024,
  memorySize: 1024 * 1024 * 4
})

mipsCompiler.compile();
mipsCompiler.run();

console.log(mipsCompiler.stdoutBuffer()); // This will print 0 1 2 3 4 5 6 7 8 9 

Arrays

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  void main() {
    int array = 1024;
    for(int i = 0; i < 10; i = i + 1) {
      *(array + i * 4) = i;
    }
    for(int i = 0; i < 10; i = i + 1) {
      printNumber(*(array + i * 4));
      printChar(32);
    }
  }
`, {
  stdout: 1024 * 512,
  stackPointer: 1024 * 1024,
  memorySize: 1024 * 1024 * 4
})

mipsCompiler.compile();
mipsCompiler.run();

console.log(mipsCompiler.stdoutBuffer()); // This will print 0 1 2 3 4 5 6 7 8 9 

Instructions

In order to print the mips32 instructions code we can use the method.

mipsCompiler.mips32Code().toString(true)

Example

const { Mips32Compiler } = require('mips32-compiler');

let mipsCompiler = new Mips32Compiler(`
  void main() {
    int a = 5+2*3;
  }
`, {
  stdout: 1024 * 512,
  stackPointer: 1024 * 1024,
  memorySize: 1024 * 1024 * 4
});
mipsCompiler.compile();
console.log(mipsCompiler.mips32Code().toString(true));

Will show this (without the comments).

// header part
0: OR $31 $31 $31 // zero register.
1: ADDI $22 $31 0 // split the 1024 * 1024 number into two 16 bits number in order to store it into a register.
2: ADDI $30 $31 16
3: SLL $30 $30 16
4: OR $30 $30 $22
5: ADDI $22 $31 0
6: ADDI $29 $31 8
7: SLL $29 $29 16
8: OR $29 $29 $22
// Header part
9: J 10
10: NOOP // Main method
11: ADDI $0 $31 2
12: ADDI $1 $31 3
13: MULT $0 $1
14: ADDI $2 $26 0 // store LO part register in $2
15: SW $2 0($30) // Adds the result to the stack
16: ADDI $30 $30 4 // Increase the stack pointer with 4
17: ADDI $0 $31 5 // Store 5 into 0 register.
18: ADDI $28 $31 4 
19: SUB $28 $30 $28 // Set stack pointer for variable 'a' in register 28
20: LW $1 0($28) // Loads the (5*3) result into $1 register from [stack_pointer - 4] position.
21: ADD $2 $0 $1 // adds the result and stores it into $2 register.
22: ADDI $28 $31 4
23: SUB $30 $30 $28 // pops the stack from the main method.

There is also a config for some of the registers which hold stuff such as stack pointer, high, low (for mult and div) and other such stuff

{
  zeroReg: 31, // The register which holds value 0.
  stackPointerRegister: 30, // The register which holds the stack pointer
  stddoutRegister: 29, // Deprecated register.
  freeRegister: 28, // General purpose register used for operations substitutions.
  hi: 27, 
  lo: 26,
  testRegister: 25,
  rsp: 24, // The register which holds the return value after a function call.
  ret: 23, // The register which holds the address where the pc should go after the method yields.
  bitSplitterRegister: 22, // A register used for splitting immediates which are higher then 16 bits.
}

What it can do

  • Compilation messages in case of errors (although quite limited in what they offer).
  • Methods usage.
  • Expressions definitions.
  • Initializations.
  • Assignations.
  • Code blocks.
  • General pointers access. (Full access to the entire memory).
  • Loops.

Limitations and problems.

  • The compiler processes only 4 bytes signed integers.
  • There are no definitions for stack pointers (int a[100]), a[1]=.... but there is general access to the memory of the program through pointers.
    int a = 5000;
    *a = 150;
  • No direct negative numbers definitions.
    // is not allowed.
    int c = -5;
    // is allowed.
    int c = 0 - 5;
  • Even if the asm is mips32, in order to be translated to valid binaries, the amount of generated instructions should be less then 64kb (j jumps support 24 bits address jump but BEQ $a $b label supports only 16 bits offset jump and the compiler does not split the a 32 bits label into 16 bits numbers).
  • Assignations are not threated as expressions so things like a = b = c; is not considered as valid code.
  • No comments.
  • No instructions assignations such as a++, a += 2, etc...;
  • Might suffer some weird compilation error problems due to bugs.

Notes

The compiler might not be complete and lacks things that C language already have, however it might be a good way to be used for simple MIPS32.