@@ -112,6 +112,10 @@ rv_csr_mscratch_3 = 0x4B
112112stack_base = 0x4C
113113rv_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
170165fetch_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
40144087emulator_size:
40154088 ; The size of the emulator, in bytes, as a little-endian 32-bit
0 commit comments