[Oberon] Implementing unsigned right shift for Oberon RISC5 machine

Joerg joerg.straube at iaeth.ch
Wed Apr 12 01:38:55 CEST 2023


Hi

An alternative to Peter’s instruction sequence is to add the LSR operation to the RISC5 instruction set.
This could be done in a backward compatible way by setting the u-bit in the ASR operation.

Add an aditional flag to RightShifter.v (eg by increasing the md-flag to two bits)

RISC5.v
RightShifter RSUnit(.x(B), .y(rshout), .sc(C1[4:0]), .md({u,IR[16]}));
RightShifter.v
module RightShifter(
input [31:0] x,
input [4:0] sc,
input [1:0] md,
output [31:0] y);

// shifter for ASR and ROR
wire [1:0] sc0, sc1;
wire [31:0] s1, s2;

assign sc0 = sc[1:0];
assign sc1 = sc[3:2];

assign s1 = (sc0 == 3) ? {(md[0]? x[2:0] :md[1] ? 3‘b0:{3{x[31]}}), x[31:3]} :
    (sc0 == 2) ? {(md[0] ? x[1:0] : md[1] ? 2‘b0:{2{x[31]}}), x[31:2]} :
    (sc0 == 1) ? {(md[0]? x[0] :md[1] ? 1’b0:x[31]), x[31:1]} : x;

assign s2 = (sc1 == 3) ? {(md[0]? s1[11:0] : md[1] ? 12‘b0:{12{s1[31]}}), s1[31:12]} :
    (sc1 == 2) ? {(md[0] ? s1[7:0] : md[1] ? 8‘b0:{8{s1[31]}}), s1[31:8]} :
    (sc1 == 1) ? {(md[0] ? s1[3:0] : md[1]? 4‘b0: {4{s1[31]}}), s1[31:4]} : s1;
assign y = sc[4] ? {(md[0]? s2[15:0] : md[1]? 16‘b0: {16{s2[31]}}), s2[31:16]} : s2;
endmodule

br
Jörg

> Am 11.04.2023 um 22:04 schrieb Peter Matthias <petermatthias at web.de>:
> 
> Not necessarily RISC5 assembler, but I think you get what I mean:
> 
> MOV R1, -1
> LSL R1, R1, Rc
> AND Rs, Rs, R1
> ROR Rd, Rs, Rc
> 
> Peter
> 
>> Am 11.04.23 um 21:27 schrieb Michael Schierl:
>> Hello,
>> 
>> 
>> as you may know, Oberon RISC5 machine only has an arithmetic right shift
>> (extending the sign) and no unsigned right shift (fillingwith zeroes).
>> For Oberon, that instruction is not needed, but what if you want other
>> languages to target the architecture?
>> 
>> 
>> I was thinking of how to implement it in a concise way
>> 
>> - No loops, as little branching as possible
>> - Having the count in a register (for a constant it is trivial to emit
>>   an additional AND to mask the bits), should work for all values from 0
>>   to 31
>> - Should work even if the destination is one of the source registers
>> - As few scratch registers as possible
>> 
>> 
>> I came up with this (using two scratch registers R1, R2):
>> 
>> USR Rd, Rs, Rc (destination, source, count) translates to
>> 
>> SUB R1, Rc, 1
>> B CS move # Rc was zero
>> ASR Rd, Rs, 1
>> MOV+U R2, 80000000H
>> ANN Rd, Rd, R2
>> ASR Rd, Rs, R1
>> B done
>> move: MOV Rd, Rs
>> done:
>> 
>> 
>> Or in case Rd is neither Rs nor Rc, you can get away with only one
>> scratch register, and the same number of instructions/branches on each
>> path:
>> 
>> ASR Rd, Rs, 1
>> MOV+U R1, 80000000H
>> ANN Rd, Rd, R1
>> SUB R1, Rc, 1
>> B CS move
>> ASR Rd, Rs, R1
>> B done
>> move: MOV Rd, Rs
>> done:
>> 
>> Any easier solution I missed?
>> 
>> 
>> Regards,
>> 
>> 
>> Michael
>> --
>> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
>> https://lists.inf.ethz.ch/mailman/listinfo/oberon
> --
> Oberon at lists.inf.ethz.ch mailing list for ETH Oberon and related systems
> https://lists.inf.ethz.ch/mailman/listinfo/oberon


More information about the Oberon mailing list