Index: cgen/cpu/toy24.cpu =================================================================== RCS file: cgen/cpu/toy24.cpu diff -N cgen/cpu/toy24.cpu --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ cgen/cpu/toy24.cpu 26 Jul 2009 01:07:43 -0000 @@ -0,0 +1,625 @@ +; 24-bit byte-size cpu description for debugging and experimental purposes. -*- Scheme -*- +; This file is part of CGEN. +; See file COPYING.CGEN for details. +; Copyright (C) 2009 Dave Korn (with willingness clearly stated to +; assign to FSF or Red Hat as appropriate at some future date). Derived +; in part from the play.cpu model, as can be seen from a few of the +; original instructions remaining. +; +; Contributed and maintained by Dave Korn +; + +(include "simplify.inc") + +(define-arch + (name toy24) ; name of cpu + (comment "experimental 24-bit bytesize .cpu file") + (default-alignment aligned) + (insn-lsb0? #t) + (machs toy24) + (isas toy24) +) + +(define-isa + (name toy24) + (default-insn-word-bitsize 24) + (default-insn-bitsize 24) + (base-insn-bitsize 24) +) + +(define-cpu + (name toy24) + (comment "experimental cpu family") + (endian big) + (insn-endian big) + (data-endian big) + (float-endian big) + (word-bitsize 24) + (file-transform "_toy24") +) + +(define-mach + (name toy24) + (comment "experimental mach") + (cpu toy24) + (isas toy24) +) + +(define-model + (name m-toy24) + (comment "test 24-bit cpu") + (mach toy24) + (unit u-exec "Execution Unit" () 1 1 () () () ()) +) + + +; Instruction formats. Nybbles of a 24-bit word are 0xABCDEF. +; All the fields are nybble-aligned for convenience. Read from +; top to bottom to get the field type: opc = opcode, rd = dest +; register, rs = source reg, rs2 = second source reg, rs3 = alt. +; source reg for single-reg-source-only instructions, im4 = 4-bit +; immediate field (currently unused by any instructions), im8 = +; 8-bit immediate field, im12 = 12-bit immediate field. +; +; word: ABCDEF +; ------ +; oorrri +; ppdssm +; cc 24 +; +; word: ABCDEF +; ------ +; oorrii +; ppdsmm +; cc 88 +; +; word: ABCDEF +; ------ +; ooriii +; ppdmmm +; cc 111 +; 222 +; +; word: ABCDEF +; ------ +; ooriii +; ppsmmm +; cc3111 +; 222 +; + + +; Instruction fields. +; Copies of all the variations. + +; big endian, lsb0? = #t +(dnf f-op1 "op1" () 23 4) +(dnf f-op2 "op2" () 19 4) + +(dnf f-rd "rd" () 15 4) +(dnf f-rs3 "rs3" () 15 4) + +(dnf f-rs "rs" () 11 4) +(dnf f-rs2 "rs2" () 7 4) + +(df f-simm4 "simm4" () 3 4 INT #f #f) +(df f-simm8 "simm8" () 7 8 INT #f #f) +(df f-simm12 "simm12" () 11 12 INT #f #f) + +(df f-uimm4 "uimm4" () 3 4 UINT #f #f) +(df f-uimm8 "uimm8" () 7 8 UINT #f #f) +(df f-uimm12 "uimm12" () 11 12 UINT #f #f) + +; PC relative, 12-bit signed displacement +(df f-disp12 "disp12" (PCREL-ADDR) 11 12 INT + ((value pc) (sub TQI value pc)) + ((value pc) (add TQI value pc))) + +; PC relative, 8-bit signed displacement +(df f-disp8 "disp8" (PCREL-ADDR) 7 8 INT + ((value pc) (sub TQI value pc)) + ((value pc) (add TQI value pc))) + + +(define-normal-insn-enum insn-op1 "insn format enums" () OP1_ f-op1 + ("JMP" "1" "LD" "ST" "ADD" "EXPERIMENTAL" "6" "7" "BRANCH" "9" "A" "B" "C" "D" "E" "F") +) + +(define-normal-insn-enum insn-op2 "insn format enums (2)" () OP2_ f-op2 + ("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F") +) + + +; Hardware. + +(dnh h-pc "program counter" (PC PROFILE) (pc) () () ()) + +(define-hardware + (name h-gr) + (comment "general registers") + (attrs PROFILE CACHE-ADDR) + (type register (UINT 24) (16)) + (indices keyword "" + ( (fp 13) (lr 14) (sp 15) + (r0 0) (r1 1) (r2 2) (r3 3) (r4 4) (r5 5) (r6 6) (r7 7) + (r8 8) (r9 9) (r10 10) (r11 11) (r12 12) (r13 13) (r14 14) (r15 15) + )) +) + +(define-hardware + (name h-status) + (comment "status reg") + (type register (UINT 24)) + (get () (const 0)) + (set (newval) (nop)) +) + +; These bits are actualy part of the PS register +(dsh h-nbit "negative bit" () (register BI)) +(dsh h-zbit "zero bit" () (register BI)) +(dsh h-vbit "overflow bit" () (register BI)) +(dsh h-cbit "carry bit" () (register BI)) + + +; Operand attributes. + +(define-attr + (for operand) + (type boolean) + (name HASH-PREFIX) + (comment "immediates have a '#' prefix") +) + +; Operands. + +(dnop nbit "negative bit" (SEM-ONLY) h-nbit f-nil) +(dnop vbit "overflow bit" (SEM-ONLY) h-vbit f-nil) +(dnop zbit "zero bit" (SEM-ONLY) h-zbit f-nil) +(dnop cbit "carry bit" (SEM-ONLY) h-cbit f-nil) +(dnop lr "link register" (SEM-ONLY) h-gr 15) + +(dnop rd "destination register" () h-gr f-rd) +(dnop rs "source register" () h-gr f-rs) +(dnop rs2 "source register 2" () h-gr f-rs2) +(dnop rs3 "alt. source register" () h-gr f-rs3) + +(dnop simm4 "4 bit signed immediate" (HASH-PREFIX) h-sint f-simm4) +(dnop simm8 "8 bit signed immediate" (HASH-PREFIX) h-sint f-simm8) +(dnop simm12 "12 bit signed immediate" (HASH-PREFIX) h-sint f-simm12) + +(dnop uimm4 "4 bit unsigned immediate" (HASH-PREFIX) h-uint f-uimm4) +(dnop uimm8 "8 bit unsigned immediate" (HASH-PREFIX) h-uint f-uimm8) +(dnop uimm12 "12 bit unsigned immediate" (HASH-PREFIX) h-uint f-uimm12) + +(dnop disp8 "8 bit pc-relative disp" () h-iaddr f-disp8) +(dnop disp12 "12 bit pc-relative disp" () h-iaddr f-disp12) + + + +; Instructions. + +; Group OP1_ADD: +; +; OP2_0: add OP2_8: addc +; OP2_1: addv2 OP2_9: addcv2 +; OP2_2: addi12 OP2_A: addui12 +; OP2_3: addi8 OP2_B: addui8 +; OP2_4: sub OP2_C: subc +; OP2_5: subv2 OP2_D: subcv2 +; OP2_6: subi12 OP2_E: subui12 +; OP2_7: subi8 OP2_F: subui8 +; + +(dni add "add" + () + "add $rd,$rs,$rs2" + ; Use (f-op1 OP1_ADD) to exercise it. + (+ (f-op1 OP1_ADD) OP2_0 rd rs rs2 uimm4) + (sequence () + (set vbit (add-oflag rs rs2 (const 0))) + (set cbit (add-cflag rs rs2 (const 0))) + (set rd (add rs rs2)) + (set zbit (zflag rd)) + (set nbit (nflag rd))) + () +) + +(dni addc "addc" + () + "addc $rd,$rs,$rs2" + ; Use (f-op1 OP1_ADD) to exercise it. + (+ (f-op1 OP1_ADD) OP2_8 rd rs rs2 uimm4) + (sequence () + (set vbit (add-oflag rs rs2 (const 0))) + (set cbit (add-cflag rs rs2 cbit)) + (set rd (addc rs rs2 cbit)) + (set zbit (zflag rd)) + (set nbit (nflag rd))) + () +) + +(dni addv2 "add version 2" + () + "addv2 $rd,$rs,$rs2" + (+ OP1_ADD OP2_1 rd rs rs2 uimm4) + (sequence ((TQI tmp1)) + (parallel () + (set tmp1 (add rs rs2)) + (set vbit (add-oflag rs rs2 (const 0))) + (set cbit (add-cflag rs rs2 (const 0)))) + (set zbit (zflag tmp1)) + (set nbit (nflag tmp1)) + (set rd tmp1) + ) + () +) + +(dni addcv2 "addc version 2" + () + "addcv2 $rd,$rs,$rs2" + (+ OP1_ADD OP2_9 rd rs rs2 uimm4) + (sequence ((TQI tmp1)) + (parallel () + (set tmp1 (addc rs rs2 cbit)) + (set vbit (add-oflag rs rs2 (const 0))) + (set cbit (add-cflag rs rs2 cbit))) + (set zbit (zflag tmp1)) + (set nbit (nflag tmp1)) + (set rd tmp1) + ) + () +) + +(dni addi12 "addi12" + () + "addi12 $rd,$simm12" + (+ OP1_ADD OP2_2 rd simm12) + (set rd (add rd simm12)) + () +) + +(dni addi8 "addi8" + () + "addi8 $rd,$rs,$simm8" + (+ OP1_ADD OP2_3 rd rs simm8) + (set rd (add rs simm8)) + () +) + +(dni addui12 "addui12" + () + "addui12 $rd,$uimm12" + (+ OP1_ADD OP2_A rd uimm12) + (set rd (add rd uimm12)) + () +) + +(dni addui8 "addui8" + () + "addui8 $rd,$rs,$uimm8" + (+ OP1_ADD OP2_B rd rs uimm8) + (set rd (add rs uimm8)) + () +) + +; Apologies for cut'n'paste coding. + +(dni sub "sub" + () + "sub $rd,$rs,$rs2" + ; Use (f-op1 OP1_ADD) to exercise it. + (+ (f-op1 OP1_ADD) OP2_4 rd rs rs2 uimm4) + (sequence () + (set vbit (sub-oflag rs rs2 (const 0))) + (set cbit (sub-cflag rs rs2 (const 0))) + (set rd (sub rs rs2)) + (set zbit (zflag rd)) + (set nbit (nflag rd))) + () +) + +(dni subc "subc" + () + "subc $rd,$rs,$rs2" + ; Use (f-op1 OP1_ADD) to exercise it. + (+ (f-op1 OP1_ADD) OP2_C rd rs rs2 uimm4) + (sequence () + (set vbit (sub-oflag rs rs2 (const 0))) + (set cbit (sub-cflag rs rs2 cbit)) + (set rd (subc rs rs2 cbit)) + (set zbit (zflag rd)) + (set nbit (nflag rd))) + () +) + +(dni subv2 "sub version 2" + () + "subv2 $rd,$rs,$rs2" + (+ OP1_ADD OP2_5 rd rs rs2 uimm4) + (sequence ((TQI tmp1)) + (parallel () + (set tmp1 (sub rs rs2)) + (set vbit (sub-oflag rs rs2 (const 0))) + (set cbit (sub-cflag rs rs2 (const 0)))) + (set zbit (zflag tmp1)) + (set nbit (nflag tmp1)) + (set rd tmp1) + ) + () +) + +(dni subcv2 "subc version 2" + () + "subcv2 $rd,$rs,$rs2" + (+ OP1_ADD OP2_D rd rs rs2 uimm4) + (sequence ((TQI tmp1)) + (parallel () + (set tmp1 (subc rs rs2 cbit)) + (set vbit (sub-oflag rs rs2 (const 0))) + (set cbit (sub-cflag rs rs2 cbit))) + (set zbit (zflag tmp1)) + (set nbit (nflag tmp1)) + (set rd tmp1) + ) + () +) + +(dni subi12 "subi12" + () + "subi12 $rd,$simm12" + (+ OP1_ADD OP2_6 rd simm12) + (set rd (sub rd simm12)) + () +) + +(dni subi8 "subi8" + () + "subi8 $rd,$rs,$simm8" + (+ OP1_ADD OP2_7 rd rs simm8) + (set rd (sub rs simm8)) + () +) + +(dni subui12 "subui12" + () + "subui12 $rd,$uimm12" + (+ OP1_ADD OP2_E rd uimm12) + (set rd (sub rd uimm12)) + () +) + +(dni subui8 "subui8" + () + "subui8 $rd,$rs,$uimm8" + (+ OP1_ADD OP2_F rd rs uimm8) + (set rd (sub rs uimm8)) + () +) + + +; Group OP1_EXPERIMENTAL: +; +; OP2_0: OP2_8: +; OP2_1: OP2_9: +; OP2_2: ldm OP2_A: +; OP2_3: use-ifield OP2_B: +; OP2_4: index-of OP2_C: +; OP2_5: OP2_D: +; OP2_6: OP2_E: +; OP2_7: OP2_F: +; + +(define-pmacro (reg+ oprnd n) + (reg h-gr (add (index-of oprnd) (const n))) +) + +(dni ldm "ldm" + () + "ldm $rd,$rs" + (+ OP1_EXPERIMENTAL OP2_2 rd rs simm8) + (sequence () + (set rd rs) + (set (reg+ rd 1) (reg+ rs 1)) + ) + () +) + +(dni use-ifield "use-ifield" + () + "foo $rd,$rs" + (+ OP1_EXPERIMENTAL OP2_3 rd rs simm8) + (sequence () + (set rd (ifield f-rs)) + ) + () +) + +(dni use-index-of "index-of" + () + "index-of $rd,$rs" + (+ OP1_EXPERIMENTAL OP2_4 rd rs simm8) + (set rd (reg h-gr (add (index-of rs) (const 1)))) + () +) + +; Group OP1_LD: Group OP1_ST: +; +; OP2_0: OP2_8: OP2_0: OP2_8: +; OP2_1: ld OP2_9: OP2_1: st OP2_9: +; OP2_2: ldb OP2_A: OP2_2: stb OP2_A: +; OP2_3: ldub OP2_B: OP2_3: stub OP2_B: +; OP2_4: OP2_C: OP2_4: OP2_C: +; OP2_5: OP2_D: OP2_5: OP2_D: +; OP2_6: OP2_E: OP2_6: OP2_E: +; OP2_7: OP2_F: OP2_7: OP2_F: +; + +(define-pmacro (load-store-op suffix op2-op mode ext-op) + (.let ( + (no-ext-expr (.pmacro (mode expr) expr)) + (ext-expr (.pmacro (mode expr) (ext mode expr))) + (zext-expr (.pmacro (mode expr) (zext mode expr))) + ) + (begin + (dni (.sym ld suffix) (.str "ld" suffix) + () + (.str "ld" suffix " $rd,$simm8[$rs]") + (+ OP1_LD op2-op rd rs simm8) + (set rd (ext-op TQI (mem mode rs))) + ()) + (dni (.sym st suffix) (.str "st" suffix) + () + (.str "st" suffix " $simm8[$rd],$rs") + (+ OP1_ST op2-op rd rs simm8) + (set (mem mode rd) (ext-op TQI rs)) + ()) + ) + ) +) + +(load-store-op "" OP2_1 TQI no-ext-expr) +(load-store-op b OP2_2 QI ext-expr) +(load-store-op ub OP2_3 QI zext-expr) + +;(load-op h OP2_10 HI ext-expr) +;(load-op uh OP2_11 HI zext-expr) + +; Group OP1_JMP: +; +; OP2_0: jmp OP2_8: jmps +; OP2_1: jmpr OP2_9: +; OP2_2: jmpl OP2_A: jmpls +; OP2_3: jmplr OP2_B: +; OP2_4: OP2_C: +; OP2_5: OP2_D: +; OP2_6: OP2_E: +; OP2_7: OP2_F: +; + +(dni jmp "jump (pc-rel iaddr)" + () + "jmp ${disp12}" + (+ OP1_JMP OP2_0 rs3 disp12) + (set pc disp12) + () +) + +(dni jmps "jump (short pc-rel iaddr)" + () + "jmps ${disp8}" + (+ OP1_JMP OP2_8 rd rs disp8) + (set pc disp8) + () +) + +(dni jmpr "jump register (absolute iaddr)" + () + "jmpr $rs3" + (+ OP1_JMP OP2_1 rs3 disp12) + (set pc rs3) + () +) + +(dni jmpl "jump and link (pc-rel iaddr)" + () + "jmpl ${disp12}" + (+ OP1_JMP OP2_2 rs3 disp12) + (sequence () + (set lr (add pc 1)) + (set pc disp12) + ) + () +) + +(dni jmpls "jump and link (short pc-rel iaddr)" + () + "jmpls ${disp12}" + (+ OP1_JMP OP2_A rd rs disp8) + (sequence () + (set lr (add pc 1)) + (set pc disp8) + ) + () +) + +(dni jmplr "jump and link register (absolute iaddr)" + () + "jmplr $rs3" + (+ OP1_JMP OP2_3 rs3 disp12) + ; If LR is early-clobbered, "jmplr lr" will blow up, so we + ; have to use a temporary. + (sequence ((TQI tmp-reg)) + (set tmp-reg rs3) + (set lr (add pc 1)) + (set pc tmp-reg)) + () +) + + +; Group OP1_BRANCH: +; +; OP2_0: jeq OP2_8: jeqs +; OP2_1: jne OP2_9: jnes +; OP2_2: jmi OP2_A: jmis +; OP2_3: jpl OP2_B: jpls +; OP2_4: jov OP2_C: jovs +; OP2_5: jnv OP2_D: jnvs +; OP2_6: jcs OP2_E: jcss +; OP2_7: jcc OP2_F: jccs +; + +(define-pmacro (branches cond op2 testbit negcond negop2) + (begin + (dni (.sym j cond) (.str "j" cond) + () + (.str "j" cond " $rs3,${disp12}") + (+ OP1_BRANCH op2 rs3 disp12) + (set pc (if testbit disp12 pc)) + ()) + (dni (.sym j negcond) (.str "j" negcond) + () + (.str "j" negcond " $rs3,${disp12}") + (+ OP1_BRANCH negop2 rs3 disp12) + (set pc (if testbit pc disp12)) + ()) + (dni (.sym j cond s) (.str "j" cond "s") + () + (.str "j" cond "s $rs,${disp8}") + (+ OP1_BRANCH op2 rd rs disp8) + (set pc (if testbit disp8 pc)) + ()) + (dni (.sym j negcond s) (.str "j" negcond "s") + () + (.str "j" negcond "s $rs,${disp8}") + (+ OP1_BRANCH negop2 rd rs disp8) + (set pc (if testbit pc disp8)) + ()) + ) +) + +(branches eq OP2_0 zbit ne OP2_2) +(branches mi OP2_4 nbit pl OP2_6) +(branches ov OP2_8 vbit nv OP2_A) +(branches cs OP2_C cbit cc OP2_E) + + +; Macro instructions: + +(dnmi nop "nop" + () + "nop" + (emit addui12 (rd 0) (uimm12 0)) ; addui12 r0,r0,#0 +) + +(dnmi ret "ret" + () + "ret" + (emit jmpr (rs3 lr) (disp12 0)) ; jmpr r15 +) + +(dnmi mov "mov" + () + "mov $rd,$rs" + (emit addui8 rd rs (uimm8 0)) ; addui8 rd,rs,#0 +) + Index: cgen/cpu/toy24.opc =================================================================== RCS file: cgen/cpu/toy24.opc diff -N cgen/cpu/toy24.opc --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ cgen/cpu/toy24.opc 26 Jul 2009 01:07:43 -0000 @@ -0,0 +1,21 @@ +/* Toy24 opcode support. -*- C -*- + Copyright (C) 2009 Dave Korn (with willingness clearly stated to + assign to FSF or Red Hat as appropriate at some future date). Derived + in part from the play.cpu model, as can be seen from a few of the + original instructions remaining. + This file is part of CGEN. */ + +/* This file is an addendum to toy24.cpu. Heavy use of C code isn't + appropriate in .cpu files, so it resides here. This especially applies + to assembly/disassembly where parsing/printing can be quite involved. + Such things aren't really part of the specification of the cpu, per se, + so .cpu files provide the general framework and .opc files handle the + nitty-gritty details as necessary. + + Each section is delimited with start and end markers. + + -opc.h additions use: "-- opc.h" + -opc.c additions use: "-- opc.c" + -asm.c additions use: "-- asm.c" + -dis.c additions use: "-- dis.c" + -ibd.h additions use: "-- ibd.h" */