From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM autolearn=unavailable autolearn_force=no version=3.4.4 X-Received: by 2002:a05:620a:b06:: with SMTP id t6mr7500224qkg.373.1579948636233; Sat, 25 Jan 2020 02:37:16 -0800 (PST) X-Received: by 2002:aca:4b46:: with SMTP id y67mr2087344oia.121.1579948635754; Sat, 25 Jan 2020 02:37:15 -0800 (PST) Path: eternal-september.org!reader01.eternal-september.org!feeder.eternal-september.org!aioe.org!peer03.am4!peer.am4.highwinds-media.com!peer02.iad!feed-me.highwinds-media.com!news.highwinds-media.com!g89no9088799qtd.0!news-out.google.com!w29ni365qtc.0!nntp.google.com!g89no9088797qtd.0!postnews.google.com!google-groups.googlegroups.com!not-for-mail Newsgroups: comp.lang.ada Date: Sat, 25 Jan 2020 02:37:15 -0800 (PST) In-Reply-To: Complaints-To: groups-abuse@google.com Injection-Info: google-groups.googlegroups.com; posting-host=47.136.24.151; posting-account=o_Y23woAAACPYGlDsFV1OivhygPNSoRn NNTP-Posting-Host: 47.136.24.151 References: User-Agent: G2/1.0 MIME-Version: 1.0 Message-ID: <01f6b6cc-9ce6-43b8-9c67-5595fa960381@googlegroups.com> Subject: Re: Creating several types from a base type and conversion From: Ken Roberts Injection-Date: Sat, 25 Jan 2020 10:37:16 +0000 Content-Type: text/plain; charset="UTF-8" X-Received-Bytes: 8421 X-Received-Body-CRC: 3433847275 Xref: reader01.eternal-september.org comp.lang.ada:57942 Date: 2020-01-25T02:37:15-08:00 List-Id: It might be that I can only really concentrate on learning Ada on my weekends (thursday night -> saturday) subject to $HoneyDoList. Needless to say, I'm not always the brightest nowadays between age and free time without some extra help, so sorry for seeming a little dense right now. Here's the computer representation as expressed in documentation and how I'm used to working on the hardware: 30-bit words (both memory storage and hardware registers) Bit Number : 29 28 .. 01 00 MSBit on left, LSBit on right 30-bit words using half-word (memory access only) Bit number: 29 28 .. 16 15 14 13 .. 01 00 Half word : | Upper | Lower | Instruction format: Bit number: | 29 .. 24 | 23 .. 21 | 20 .. 18 | 17 .. 15 | 14 .. 0 | Field : | Op code | J | K | B | Y | Op code : Instruction j : Skip next instruction modification k : Source or destination of data b : Index register to use to modify Y y : Constant or memory address Sample program 1 (all numbering is octal notation): | Address | Contents | Description | 00600 | 12130 00601 | f = 12 : Opcode (Load A register) | | | j = 1 : 1 = always skip next instruction | | | k = 3 : y is memory address, 30 bits | | | y = 601 : Data | 00601 | 00005 00001 | Data | | | A register initial: 00005 00001 | 00602 | 06000 00017 | f = 06 : Opcode (Shift A left circular) | | | j = 0 : Execute next instruction | | | k = 0 : Shift count is y | | | y = 17 : Data (17 octal, 15 decimal) | | | A register final: 00001 00005 Sample program using 60-bit register instruction: 60-bit register Bit number : | 59 .. 30 | 29 .. 00 | Registers used : | A reg | Q reg | | Address | Contents | Description | 00600 | 10000 00001 | Load Q register | | | Q register = 00000 00001 | 00601 | 11000 00005 | Load A register | | | A register = 00000 00005 | 00602 | 07000 00036 | Left shift AQ register circular | | | Shift count (36 octal, 30 decimal) | | | | | | AQ initial : 00000 00005 00000 00001 | | | A register initial = 00000 00005 | | | Q register initial = 00000 00001 | | | | | | AQ final : 00000 00001 00000 00005 | | | A register final = 00000 00001 | | | Q register final = 00000 00005 My programming environment is: Intel-based system 64-bit Fedora based KDE desktop system Fedora repository has the GNAT compiler suite (GCC Ada - AdaCore?) With these considerations in mind, I'm trying to figure out the best way to represent the computer hardware (register and memory). The register and memory base word would be a 30-bit quantity (Interfaces.unsigned_32 possibly?) with 2**30 bit limit, so all register/memory representations would be easily convertible. Memory representation will be an array (0 .. #8#77777# or 32,768 words) of 30-bit words. The 60-bit instructions (there's only 2 shift instructions, multiply, which puts answer in QA register(s)) and divide, which uses combined QA register for data, and puts answer in Q and remainder in A)) Based on Niklas Holsti's recommendation, it looks like the following would be what I want to do: package core is with Interfaces; subtype Word is Interfaces.Unsigned_32 with range 0 .. 2**30 - 1; subtype D_Word is Interfaces.Unsigned_64 with record Ru : Word; Rl : Word; end record for D_Word use record Ru : at 0 use 59 .. 30; Rl : at 0 use 29 .. 0; end record -- NOTE: I_Word is basically read-only -- The only use is to make it easier to break down Word into -- the fields to interpret the instruction and will not change -- during the instruction execution cycle I_Word is Word with record -- Not sure how to define this part yet -- See below for breakdown of bits-to-fields end record for I_Word use record f : at 0 range 29 .. 24; j : at 0 range 23 .. 21; k : at 0 range 20 .. 18; b : at 0 range 17 .. 15; y : at 0 range 14 .. 00; end record end package core; With the above representation, I can use a D_Word for shifting and be able to ignore unused 32/64 bits in hardware -- Circular left shift register procedure shift_left_logical (R : <> Word'Class, Count : in Integer) is private D : D_Word; -- NOTE: By putting the same contents into both Ru and Rl -- I don't have to worry about extra bits from Unsigned_32 D.Ru := R; D.Rl := R; -- NOTE: Only bits 5 .. 0 are used, the rest are ignored -- Add option to limit actual shifting to mod 30 since anything -- over 30 would just wrap around again -- ex: Count == 31 is equivalent to Count == 1 -- on a 30-bit register if Count > 8#77# then C : Integer (Count and 8#77#); else C : Integer (Count); end if Count; end private; begin D.Shift_Left(C); -- Set the register to new value R := D.Ru; end shift_left_logical; For the double-register shift -- Circular left shift double register procedure double_shift_left_logical (R1 : <> Word'Class, R2 : <> Word'Class, Count : in Integer) is private D1 : D_Word; D2 : D_Word; -- Normal register order so lower register bits go to upper register D1.Ru := R1; -- A register D1.Rl := R2; -- Q register -- Reverse the register order so high register bits go to low register D2.Ru := R2; -- Q register D2.Rl := R1; -- A register -- NOTE: Only bits 5 .. 0 are used, the rest are ignored -- Add option to limit actual shifting to mod 60 since anything -- over 60 would just wrap around again -- ex: Count == 61 is equivalent to Count == 1 -- on a 60-bit register if Count > 8#77# then C : Integer (Count and 8#77#); else C : Integer (Count); end if Count; end private; begin D1.Shift_Left(C); -- AQ register pair D2.Shift_Left(C); -- QA register pair -- Set the registers to new values R1 := D1.Ru; -- A register R2 := D2.Ru; -- Q Register end shift_left_logical; This is from my limited understanding so far. Thanks for all of your help - I wish I could catch on a little quicker, but age and $DayJob (plus $HoneyDoList) make learning a new language a little challenging lately.