commit e4f8168882930df9b5947a9ac146cb176c4fad53
parent c2e829caab204946155130c494312cf543871f68
Author: Michail Konstantinos Dimopoulos <mk@mcdim.xyz>
Date: Sun, 22 Mar 2026 01:07:16 +0200
Stores added
Diffstat:
| M | main.c | | | 179 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
1 file changed, 170 insertions(+), 9 deletions(-)
diff --git a/main.c b/main.c
@@ -2,6 +2,9 @@
#include <stdio.h>
#include <stdlib.h>
+#define MEMSIZE 2052
+
+
typedef struct {
uint32_t x[32]; /* general purpose registers */
uint32_t pc;
@@ -15,11 +18,19 @@ typedef struct {
typedef struct {
uint8_t opcode;
- uint8_t rd, rs1, imm;
+ uint8_t rd, rs1;
+ uint16_t imm;
uint8_t funct3;
uint8_t funct7, inimm;
} itype_t;
+typedef struct {
+ uint8_t opcode;
+ uint8_t rs1, rs2;
+ uint16_t imm;
+ uint8_t funct3;
+} stype_t;
+
void print_bin16(uint16_t x) {
for (int i = 15; i >= 0; i--) {
putchar((x >> i) & 1 ? '1' : '0');
@@ -61,7 +72,7 @@ void exec_itype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
/**print**/
printf("f7 rs2 rs1 f3 rd opcode\n");
- print_binless(i.imm, 11);
+ print_binless(i.imm, 12);
printf(" ");
print_binless(i.rs1, 5);
printf(" ");
@@ -264,7 +275,7 @@ void exec_ltype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
/**print**/
printf("imm rs1 f3 rd opcode\n");
- print_binless(i.imm, 11);
+ print_binless(i.imm, 12);
printf(" ");
print_binless(i.rs1, 5);
printf(" ");
@@ -274,19 +285,127 @@ void exec_ltype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
printf("\n");
/*********/
+ int32_t addr = i.imm + cpu->x[i.rs1];
+
+ /* TODO: do I need to check before loading halves and words */
+
int32_t x;
switch(i.funct3) {
case 0x0:
- x = (int8_t)mem[i.imm+i.rs1];
+ printf("Load byte\n");
+ x = (uint32_t)(int32_t)(int8_t)mem[addr];
break;
+ case 0x1:
+ printf("Load half, little endian\n");
+ uint16_t half = (uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8);
+ x = (uint32_t)(int32_t)(int16_t)half;
+ break;
+ case 0x2:
+ printf("Load word, little endian");
+ x = (uint32_t)(int32_t)(
+ ((uint16_t)mem[addr] | ((uint16_t)mem[addr+1] << 8))
+ |
+ (((uint16_t)mem[addr+2] | ((uint16_t)mem[addr+3] << 8))
+ << 16)
+ );
+ break;
+ case 0x4:
+ printf("Load byte (U) zero-extends\n");
+ x = (uint32_t)(uint32_t)(uint8_t)mem[addr];
+ break;
+
+ case 0x5:
+ printf("Load half, little endian\n");
+ int16_t uhalf = (int16_t)mem[addr] | ((int16_t)mem[addr+1] << 8);
+ x = (uint32_t)(int32_t)uhalf;
+ break;
+ default:
+ fprintf(stderr, "Illegal funct3\n");
+ return;
}
if (i.rd != 0) {
cpu->x[i.rd] = x;
}
- printf("rd:%d\n", cpu->x[i.rd]);
+ printf("\nrd:%d\n", cpu->x[i.rd]);
+ printf("rd:%x\n", cpu->x[i.rd]);
+
+}
+
+/*
+S-TYPE INSTRUCTION FORMAT
+31 25 24 20 19 15 14 12 11 7 6 0
++------------+--------+--------+--------+---------+--------+
+| imm[11:0] | rs2 | rs1 | funct3 |imm[4:0] | opcode |
++------------+--------+--------+--------+---------+--------+
+opcode 0x33 0100011
+*/
+void exec_stype(cpu_state_t *cpu, uint32_t inst, uint8_t *mem) {
+ printf("TYPE S\n");
+ stype_t s;
+
+ uint32_t imm_11_5 = (inst >> 25) & 127;
+ uint32_t imm_4_0 = (inst >> 7) & 31;
+ s.imm = (imm_4_0) | (imm_11_5 << 5);
+
+ s.funct3 = (inst >> 12) & 7;
+ s.rs1 = (inst >> 15) & 31;
+ s.rs2 = (inst >> 20) & 31;
+
+ printf("\nimm:%x\n", s.imm);
+
+ /**print**/
+ printf("imm rs2 rs1 f3 imm opcode\n");
+ printf("[11:5] [4:0]\n");
+ print_binless(imm_11_5, 7);
+ printf(" ");
+ print_binless(s.rs2, 5);
+ printf(" ");
+ print_binless(s.rs1, 5);
+ printf(" ");
+ print_binless(s.funct3, 3);
+ printf(" ");
+ print_binless(imm_4_0, 5);
+ printf("\n");
+ /*********/
+
+ uint32_t addr = s.imm + cpu->x[s.rs1];
+ switch(s.funct3) {
+ case 0x0:
+ printf("STORE BYTE\n");
+ mem[addr] = cpu->x[s.rs2] & 255;
+ break;
+ case 0x1:
+ printf("STORE half, little endian\n");
+ if (addr+1 > MEMSIZE-1) {
+ fprintf(stderr, "Illegal addr\n");
+ return;
+ }
+
+ if (addr % 2 == 0) {
+ mem[addr] = cpu->x[s.rs2];
+ mem[addr+1] = cpu->x[s.rs2] >> 8;
+ }
+ break;
+ case 0x2:
+ printf("STORE word, little endian\n");
+ if (addr+3 > MEMSIZE-1) {
+ fprintf(stderr, "Illegal addr\n");
+ return;
+ }
+ if (addr % 4 == 0) {
+ mem[addr] = cpu->x[s.rs2];
+ mem[addr+1] = cpu->x[s.rs2] >> 8;
+ mem[addr+2] = cpu->x[s.rs2] >> 16;
+ mem[addr+3] = cpu->x[s.rs2] >> 24;
+ }
+ break;
+ default:
+ fprintf(stderr, "Illegal funct3\n");
+ return;
+ }
}
int main() {
@@ -298,6 +417,7 @@ int main() {
opcode_table[0x33] = exec_rtype;
opcode_table[0x13] = exec_itype;
opcode_table[0x03] = exec_ltype;
+ opcode_table[0x23] = exec_stype;
/*opcode_table[0x13] = exec_rtype_imm;
opcode_table[0x03] = exec_load;
opcode_table[0x23] = exec_store;
@@ -336,16 +456,44 @@ int main() {
// imm rs1 f3 rd opcode
// 000000000101 00010 111 00011 0010011
- //inst = 0x517193; /* ANDi 101 */
+ inst = 0x517193; /* ANDi 101 */
// imm rs1 f3 rd opcode
// 000000000001 00010 101 00011 0010011
- //inst = 0x115193; /* shift logical right i 1*/
+ inst = 0x115193; /* shift logical right i 1*/
// imm rs1 f3 rd opcode
// 011111111111 00000 000 00011 0000011
inst = 0x100183; /* LOAD Byte from address 0x3*/
+ // imm rs1 f3 rd opcode
+ // 000000000000 00000 001 00011 0000011
+ inst = 0x1183; /* LOAD half from address 0x0*/
+
+ // imm rs1 f3 rd opcode
+ // 000000000000 00000 010 00011 0000011
+ inst = 0x2183; /* LOAD word from address 0x0*/
+
+ // imm rs1 rs2 f3 imm opcode
+ // [11:5] [4:0]
+ // 0000000 00000 00000 000 00000 0100011
+ inst = 0x23; /* STORE rs2 contents to mem 0x0*/
+
+ // imm rs2 rs1 f3 imm opcode
+ // [11:5] [4:0]
+ // 0000000 00000 00000 000 00010 0100011
+ inst = 0xA3; /* STORE rs2 contents to mem 0x0*/
+
+ // imm rs2 rs1 f3 imm opcode
+ // [11:5] [4:0]
+ // 0000000 00000 00000 010 00100 0100011
+ inst = 0x2223; /* STORE rs2 contents to mem 0x04 (word)*/
+
+ // imm rs2 rs1 f3 imm opcode
+ // [11:5] [4:0]
+ // 0000000 00000 00000 010 00011 0100011
+ inst = 0x21A3; /* STORE rs2 contents to mem 0x03, FAIL (word)*/
+
print_bin32(inst);
printf("\n");
@@ -357,12 +505,22 @@ int main() {
exec_fn fn = opcode_table[opcode];
cpu_state_t cpu;
+ /* init cpu state */
+ for (int i=0; i<32; i++) {
+ cpu.x[i] = 0;
+ }
cpu.x[1] = 51;
- cpu.x[2] = 14;
- uint8_t mem[2056] = {0};
+ cpu.x[2] = 00;
+
+ uint8_t mem[MEMSIZE] = {0};
+ /* set mem for test */
for (int i=0; i<2056; i++) {
mem[i] = (uint8_t)i;
}
+ for (int i=0; i<32; i++) {
+ printf("0x%x: 0x%x\n", i, mem[i]);
+ }
+
if (!fn) {
//illegal(NULL, inst);
@@ -371,6 +529,9 @@ int main() {
}
fn(&cpu,inst,mem);
+ for (int i=0; i<32; i++) {
+ printf("0x%x: 0x%x\n", i, mem[i]);
+ }
return 0;
}