Skip to content

Commit ccec189

Browse files
committed
Make the number of interrupt vectors configurable
1 parent bd782ea commit ccec189

1 file changed

Lines changed: 100 additions & 27 deletions

File tree

src/main.S

Lines changed: 100 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ rv_csr_mscratch_3 = 0x4B
112112
stack_base = 0x4C
113113
rv_x0 = 0x80
114114

115+
.ifndef NUM_INTERRUPTS
116+
NUM_INTERRUPTS = 5
117+
.endif
118+
115119
.area XSEG (XDATA)
116120
.area PSEG (PAG,XDATA)
117121
.area HOME (ABS,CODE)
@@ -120,19 +124,10 @@ reset:
120124
ljmp init
121125

122126
.org 0x0003
123-
ljmp isr_eint0
124-
125-
.org 0x000b
126-
ljmp isr_timer0
127-
128-
.org 0x0013
129-
ljmp isr_eint1
130-
131-
.org 0x001b
132-
ljmp isr_timer1
133-
134-
.org 0x0023
135-
ljmp isr_serial
127+
.rept NUM_INTERRUPTS
128+
ljmp isr_common
129+
.ds 5 ; pad 3-byte ljmp out to the 8-byte vector slot
130+
.endm
136131

137132
sjmp .
138133

@@ -168,7 +163,7 @@ emu_loop:
168163
mov curr_pc_dptr_1, dph
169164

170165
fetch_instruction:
171-
; Fetch instruction
166+
; Fetch the first two bytes of the instruction.
172167
clr a
173168
movc a, @a+dptr
174169
mov instruction_0, a
@@ -177,6 +172,15 @@ fetch_instruction:
177172
movc a, @a+dptr
178173
mov instruction_1, a
179174
inc dptr
175+
176+
; An instruction whose lowest two bits aren't both set is a 16-bit
177+
; compressed (RVC) instruction. Decompress it into its equivalent
178+
; 32-bit instruction before decoding; otherwise fetch the remaining
179+
; two bytes of the full 32-bit instruction.
180+
mov a, instruction_0
181+
anl a, #0x03
182+
cjne a, #0x03, fetch_compressed
183+
180184
clr a
181185
movc a, @a+dptr
182186
mov instruction_2, a
@@ -185,7 +189,12 @@ fetch_instruction:
185189
movc a, @a+dptr
186190
mov instruction_3, a
187191
inc dptr
192+
sjmp fetch_decode
188193

194+
fetch_compressed:
195+
lcall decompress_instruction
196+
197+
fetch_decode:
189198
; Decode/execute instruction
190199
lcall decode_opcode
191200

@@ -3991,25 +4000,89 @@ interrupt_controller:
39914000
; Not vectored or not asynchronous.
39924001
ret
39934002

3994-
isr_eint0:
4003+
isr_common:
39954004
setb misc_bit0__new_interrupt
39964005
reti
39974006

3998-
isr_eint1:
3999-
setb misc_bit0__new_interrupt
4000-
reti
4007+
decompress_instruction:
4008+
; Expand a 16-bit compressed (RVC) instruction in instruction_1:0
4009+
; into its equivalent 32-bit instruction in instruction_3:0, then
4010+
; return so the normal decoder can execute it.
4011+
;
4012+
; Currently only c.addi is implemented:
4013+
; op[1:0] = 0b01, funct3 (inst[15:13]) = 0b000
4014+
; Expands to: addi rd, rd, sext(imm[5:0]), rd = inst[11:7]
4015+
; (rd == 0 is c.nop, which the OP-IMM path treats as a no-op.)
40014016

4002-
isr_timer0:
4003-
setb misc_bit0__new_interrupt
4004-
reti
4017+
; Require quadrant 1 (op[1:0] == 0b01).
4018+
mov a, instruction_0
4019+
anl a, #0x03
4020+
cjne a, #0x01, decompress_unimplemented
40054021

4006-
isr_timer1:
4007-
setb misc_bit0__new_interrupt
4008-
reti
4022+
; Require funct3 == 0b000 (instruction_1[7:5]).
4023+
mov a, instruction_1
4024+
anl a, #0xE0
4025+
jnz decompress_unimplemented
40094026

4010-
isr_serial:
4011-
setb misc_bit0__new_interrupt
4012-
reti
4027+
; Reconstruct rd (== rs1) into immediate_0 as a 5-bit value:
4028+
; rd[4:1] = instruction_1[3:0], rd[0] = instruction_0[7].
4029+
mov a, instruction_1
4030+
anl a, #0x0F
4031+
rl a
4032+
jnb (((instruction_0 - 0x20) * 8) + 7), 1$
4033+
inc a
4034+
1$:
4035+
mov immediate_0, a
4036+
4037+
; Reconstruct the 6-bit immediate into R4:
4038+
; imm[4:0] = instruction_0[6:2], imm[5] = instruction_1[4].
4039+
mov a, instruction_0
4040+
anl a, #0x7C
4041+
rr a
4042+
rr a
4043+
jnb (((instruction_1 - 0x20) * 8) + 4), 2$
4044+
orl a, #0x20
4045+
2$:
4046+
mov r4, a
4047+
4048+
; instruction_3 = sign-extended imm[11:4].
4049+
mov a, r4
4050+
swap a
4051+
anl a, #0x03
4052+
jnb (((instruction_1 - 0x20) * 8) + 4), 3$
4053+
orl a, #0xFC
4054+
3$:
4055+
mov instruction_3, a
4056+
4057+
; instruction_2 = imm[3:0] | rs1[4:1].
4058+
mov a, immediate_0
4059+
rr a
4060+
anl a, #0x0F
4061+
mov r5, a
4062+
mov a, r4
4063+
swap a
4064+
anl a, #0xF0
4065+
orl a, r5
4066+
mov instruction_2, a
4067+
4068+
; instruction_1 = rs1[0] | funct3(0b000) | rd[4:1].
4069+
mov a, immediate_0
4070+
rr a
4071+
anl a, #0x8F
4072+
mov instruction_1, a
4073+
4074+
; instruction_0 = OP-IMM opcode (0x13) | rd[0].
4075+
mov a, #0x13
4076+
jnb (((immediate_0 - 0x20) * 8) + 0), 4$
4077+
orl a, #0x80
4078+
4$:
4079+
mov instruction_0, a
4080+
4081+
ret
4082+
4083+
decompress_unimplemented:
4084+
; Unimplemented compressed instruction.
4085+
sjmp .
40134086

40144087
emulator_size:
40154088
; The size of the emulator, in bytes, as a little-endian 32-bit

0 commit comments

Comments
 (0)