Skip to content

LLVM Status – A Terrible Heinous Sunday Morning Bodge

January 4, 2015

As of yesterday afternoon I had made progress on a couple of fronts:
-I can create 1802 assembly language output and a corresponding .elf file for simple programs based on the LEG example.
-I have several different back-end examples in various states of usability.

At this stage I *think* I could start again on an 1802 native target although there are a *lot* of holes in my knowledge. I feel like I could fill in some holes by working through the cpu0 example which would be a whole new example but might be the right way to go because it seems to step right thru the back end development (except I don’t think it builds up to clang – the c++ compiler).

In the near term I’m going to focus on more pressing projects but for my records, here’s what I can do

void flipQ(void);

int main(void){
  while(1){
    flipQ();
  }
  return 0;
}
	.text
	.file	"loop.c"
	.globl	main
	.type	main,@function
main:
.LBB0_1:
	SEQ
	REQ
	NOP
	LBR .LBB0_1
.Ltmp0:
	.size	main, .Ltmp0-main


	.ident	"clang version 3.6.0 "
	.section	".note.GNU-stack","",@progbits

The money in the above gobbledygook is the five lines starting with the label .LBB0_1 and ending with LBR .LBB0_1. These constitute a variation on the classic 1802 hello world which sets, then resets the Q flipflop and loops forever.

And here is the corresponding loop.elf file generated with ../build/debug/bin/clang -cc1 -triple leg-unknown-unknown -O3 -emit-obj -o loop.o loop.c
15-01-04 ELF File
The code for the four instructions is the outlined 7B 7A C4 C00000. Just as important though, the elf file itself makes sense. For instance the section header for the .data section is outlined in red and it says the program starts at offset 34 in the file and is six bytes long.

Now this is pretty much a dead end, I have committed truly dreadful modifications to the LEG example to do it. The worst thing is that I perverted the three instructions in the “call” sequence to get my Q set/reset. The code wanted to issue a movw, a movt, and a bl but I modified each of those to generate SEQ, REQ, and NOOP respectively- wouldn’t matter what the call subject was – you’d get seq/req/nop and anywhere else you were loading a constant to boot!

To perpetrate this I modified a number of files:
In SelectionDAGISel.cpp I put some diagnostic prints
In LEGInstPrinter.cpp I commented out an assertion to do with Kind == VK_LEG_LO/HI
In LEGISelDAGToDAG.cpp I substituted COSLD2I for MOVLOi16 to load a 16 bit constant
In LEGISelLowering.cpp I return COSRET_FLAG instead of LEGRET_FLAG
In LEGInstrFormats.td I put in base classes for three cosmic instructions and changed a one of the LEG formats to be the COSNOP
In LEGInstrInfo.td i added COSLD2i, perverted the MOVLOi16 and MOVHIi16 to do the SEQ and REQ, put in the WJRBR long branch, and put in the cosmic return instruction
in LEGOperators.tf I defined COSRetFlag
In LEGAsmBackend I bodged some stuff to get Fixup_COS_Global to return an absolute value in the .elf file rather than PC relative
In LEGELFObjectWriter.cpp I did something else about Fixup_COS_Global which may not be needed or correct
In LEGFixupKinds.h I defined fixup_COS_global
In LEGMCCodeEmitter.cpp I changed a few things to accommodate instruction lengths other than 4 and accept the fixup_COS_global

diff -r /Users/bill/Documents/legc/src/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp /Users/bill/Documents/legc-baseline/src/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
2479,2481d2478
<     //dbgs() << "pre-switch: ";
<     //NodeToMatch->dump(CurDAG);
<     //dbgs() << '\n';
3295c3292
< Msg<<"pigs ";
---
> 
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/InstPrinter/LEGInstPrinter.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/InstPrinter/LEGInstPrinter.cpp
50,54c50,52
< 
<   //const MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
<   SRE->dump();
<     //assert(Kind == MCSymbolRefExpr::VK_LEG_LO ||
<     //     Kind == MCSymbolRefExpr::VK_LEG_HI);
---
>   const MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
>   assert(Kind == MCSymbolRefExpr::VK_LEG_LO ||
>          Kind == MCSymbolRefExpr::VK_LEG_HI);
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGISelDAGToDAG.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGISelDAGToDAG.cpp
87c87
<       CurDAG->getMachineNode(LEG::COSLD2I, N, MVT::i32, ConstLo); //wjr
---
>       CurDAG->getMachineNode(LEG::MOVLOi16, N, MVT::i32, ConstLo);
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGISelLowering.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGISelLowering.cpp
319c319
<   fprintf(stderr,"LowerReturn\n");
---
> 
350,351c350,351
<     printf("returning COSRET_FLAG\n");
<   return DAG.getNode(LEGISD::COSRET_FLAG, dl, MVT::Other, RetOps);
---
> 
>   return DAG.getNode(LEGISD::RET_FLAG, dl, MVT::Other, RetOps);
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGISelLowering.h /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGISelLowering.h
38d37
<   COSRET_FLAG,
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGInstrFormats.td /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGInstrFormats.td
9,61d8
< //===----------------------------------------------------------------------===//
< // 24 bit COSMAC global branch instruction
< //===----------------------------------------------------------------------===//
< class InstCOSLBR<dag outs, dag ins, string asmstr, list<dag> pattern>
< : Instruction {
<     field bits<24> Inst;
<     
<     let Namespace = "LEG";
<     dag OutOperandList = outs;
<     dag InOperandList = ins;
<     let AsmString   = asmstr;
<     let Pattern = pattern;
<     let Size = 3;
<     
<     // Set dummy values
<     let Inst{23-0} = 0x777777;
< }
< 
< //===----------------------------------------------------------------------===//
< // 8 bit COSMAC instruction
< //===----------------------------------------------------------------------===//
< class InstCOS<dag outs, dag ins, string asmstr, list<dag> pattern>
< : Instruction {
<     field bits<8> Inst;
<     
<     let Namespace = "LEG";
<     dag OutOperandList = outs;
<     dag InOperandList = ins;
<     let AsmString   = asmstr;
<     let Pattern = pattern;
<     let Size = 1;
<     
<     // Set a dummy pattern default
<     let Inst{7-0} = 0xAA;
< }
< 
< //===----------------------------------------------------------------------===//
< // 48 bit COSMAC load register immediate instruction
< //===----------------------------------------------------------------------===//
< class InstCOSldri<dag outs, dag ins, string asmstr, list<dag> pattern>
< : Instruction {
<     field bits<48> Inst;
<     
<     let Namespace = "LEG";
<     dag OutOperandList = outs;
<     dag InOperandList = ins;
<     let AsmString   = asmstr;
<     let Pattern = pattern;
<     let Size = 6;
<     
<     // Set dummy values
<     let Inst{47-0} = 0x777777777777;
< }
100c47
< class COSNOP<dag outs, dag ins,
---
> class BranchInst<bits<4> opcode, dag outs, dag ins,
102a50
>   let Inst{27-24} = opcode;
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGInstrInfo.td /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGInstrInfo.td
100a101
> 
105,119d105
< def COSLD2I : InstCOSldri<(outs GRRegs:$dst),(ins i32imm:$imm),"LD2I $dst,$imm",
< [(set i32:$dst, i32imm_lo:$imm)]>{
<     bits<4> dst;
<     bits<16> imm;
<     let Inst{7-0} =0xf8;
<     let Inst{15-8}  = imm{15-8};
<     let Inst{23-16}=0xB0;
<     let Inst{19-16}=dst;
<     let Inst{31-24} =0xf8;
<     let Inst{39-32} = imm{7-0};
<     let Inst{47-40}=0xA0;
<     let Inst{43-40}=dst;
< }
< 
< 
132,147c118,121
< class xEQ<bits<4> opcode, string opstr, dag ins, list<dag>pattern>
< : ALUInst<opcode, (outs GRRegs:$dst), ins,
< opstr, pattern> {
<     let Inst{7-4} = 7;
<     let Inst{3-0}=opcode;
<     let Size=1;
< }
< 
< //def MOVLOi16 : MOV<0b1000, "movw", (ins i32imm:$imm),
< //                  [(set i32:$dst, i32imm_lo:$imm)]>;
< def MOVLOi16 : xEQ<0b1011, "SEQ", (ins i32imm:$imm), //7B op code
< [(set i32:$dst, i32imm_lo:$imm)]>;
< //def MOVHIi16 : MOV<0b1010, "movt", (ins GRRegs:$src1, i32imm:$imm),
< //                  [/* No Pattern */]>;
< def MOVHIi16 : xEQ<0b1010, "REQ", (ins GRRegs:$src1, i32imm:$imm),
< [/* No Pattern */]>;
---
> def MOVLOi16 : MOV<0b1000, "movw", (ins i32imm:$imm),
>                   [(set i32:$dst, i32imm_lo:$imm)]>;
> def MOVHIi16 : MOV<0b1010, "movt", (ins GRRegs:$src1, i32imm:$imm),
>                   [/* No Pattern */]>;
191,208d164
< 
< //===----------------------------------------------------------------------===//
< // Dummying up a branch Instructions
< //===----------------------------------------------------------------------===//
< // Branch targets have OtherVT type (copied from SPARC)
< def brtarget : Operand<OtherVT> {
<     //let EncoderMethod = "getBranchTargetOpValue";
< }
< 
< let isBranch = 1, isTerminator = 1 in {
<     def WJRBR : InstCOSLBR<(outs), (ins brtarget:$addr),
<     "LBR $addr",
<     [(br bb:$addr)]> {
<         bits<32> addr;
<         let Inst{7-0} = 0xC0; //long branch
<         let Inst{23-8} = addr{15-0};
<     }
< }
214,228c170,173
<     def RET : InstLEG<(outs), (ins variable_ops),
<     "bx lr",  [(LEGRetFlag)]> {
<         let Inst{27-0}  = 0b0001001011111111111100011110;
<     }
< }
< 
< //===----------------------------------------------------------------------===//
< // COSMAC Return Instruction
< //===----------------------------------------------------------------------===//
< 
< let isTerminator = 1, isReturn = 1, isBarrier = 1, Uses = [LR] in {
<     def COSRET : InstCOS<(outs), (ins variable_ops),
<     "SEP 5",  [(COSRetFlag)]> {
<         let Inst{7-0}  = 0xD5;
<     }
---
>   def RET : InstLEG<(outs), (ins variable_ops),
>                     "bx lr",  [(LEGRetFlag)]> {
>     let Inst{27-0}  = 0b0001001011111111111100011110;
>   }
232d176
< 
238,246c182,183
< //  def BL : BranchInst<0b1011, (outs), (ins GRRegs:$addr),
< //                      "bl $addr",
< //                      [(leg_call i32:$addr)]> {
< //    bits<4> addr;
< //    let Inst{31-28} = 0b1110;
< //    let Inst{3-0} = addr;
< //  }
<                       def callnoop : COSNOP<(outs), (ins GRRegs:$addr),
<                       "NOP",
---
>   def BL : BranchInst<0b1011, (outs), (ins GRRegs:$addr),
>                       "bl $addr",
248,250c185,188
<                           let Inst{7-0} = 0xC4;
<                           let Size=1;
<                       }
---
>     bits<4> addr;
>     let Inst{31-28} = 0b1110;
>     let Inst{3-0} = addr;
>   }
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/LEGOperators.td /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/LEGOperators.td
24,25d23
< def COSRetFlag    : SDNode<"LEGISD::COSRET_FLAG", SDTNone,
<                           [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/MCTargetDesc/LEGAsmBackend.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/MCTargetDesc/LEGAsmBackend.cpp
58d57
<       { "fixup_COS_global", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
104d102
<   unsigned Offset = Fixup.getOffset();
108,111d105
<   case LEG::fixup_COS_global:
<     Offset=Fixup.getOffset();
<     fprintf(stderr,"Value=%d, Offset=%d, Adjfixupval returns%d\n",(int)Value, Offset, (int)(Value+Offset));
<     return Value+Offset;
147,148d140
<   
<   unsigned Offset = Fixup.getOffset();
150,156c142
<     unsigned Kind = Fixup.getKind();//wjr
<     if (Kind==LEG::fixup_COS_global){
<         NumBytes=2;
<         fprintf(stderr,"Bingo\n\n");
<     }
<     
< fprintf(stderr,"Offset=%d, NumBytes=%d, DataSize=%d\n",Offset, NumBytes, DataSize); //wjr
---
>   unsigned Offset = Fixup.getOffset();
166,171c152
< /*
<  switch (Kind) {
<  default:
<  llvm_unreachable("Unknown fixup kind!");
<  case LEG::fixup_COS_global:
< */
---
> 
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/MCTargetDesc/LEGELFObjectWriter.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/MCTargetDesc/LEGELFObjectWriter.cpp
47,50d46
<       case LEG::fixup_COS_global:// wjr
<           fprintf(stderr,"global fixup\n");
<           Type = ELF::R_ARM_NONE;//wjr
<           break;//wjr
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/MCTargetDesc/LEGFixupKinds.h /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/MCTargetDesc/LEGFixupKinds.h
20d19
<   fixup_COS_global, //wjr trying something
diff -r /Users/bill/Documents/legc/src/lib/Target/LEG/MCTargetDesc/LEGMCCodeEmitter.cpp /Users/bill/Documents/legc-baseline/src/lib/Target/LEG/MCTargetDesc/LEGMCCodeEmitter.cpp
28c28
< //#include <iostream>
---
> 
115,117c115
<     /*llvm_unreachable*/fprintf(stderr,"Unknown fixup kind! - using LEG::fixup_COS_global\n"); //wjr
<           FixupKind = LEG::fixup_COS_global;
<           break;
---
>     llvm_unreachable("Unknown fixup kind!");
148,156c146,151
<     if (Desc.getSize() > 8) { //wjr
<         llvm_unreachable("Single instruction can only be 8 bytes!");
<     }
<     
<     const uint64_t Binary = getBinaryCodeForInstr(MI, Fixups, STI); //wjr
<     //uint64_t test=0x0102030405060708;
<     printf("%016llX\n", Binary);
<     printf("+");
<     MI.dump();
---
>   if (Desc.getSize() != 4) {
>     llvm_unreachable("Unexpected instruction size!");
>   }
> 
>   const uint32_t Binary = getBinaryCodeForInstr(MI, Fixups, STI);
> 
Advertisements

From → LLVM

One Comment

Trackbacks & Pingbacks

  1. LCC1802 For The Mac? | olduino

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: