Skip to content

Hah! – Found IT! Plus another non-pro Mac Tip

I’m an old command line hand but a desperate mac newbie.  I like OS X command line but it has a very busy prompt for a single user system. This helpful goody showed me how to change it with
export PS1=”\e[0;31m\w>\e[m “
I also learned to edit my logon profile with
nano ~/.bash_profile
and to make it take effect right away with
source ~/.bash_profile

Now, the reason I was at the command line is I was trying to figure out how to change the format of the assembler labels that are emitted by LLVM so my assembler would allow them. For example:

int main(void){
  while(1){
    flipQ();
  }
  return 0;
}
----------------generates
	.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

I looked in what seemed like all the sensible and recommended places, I found
PrivateGlobalPrefix = “.L”;
but changing it had no effect. Finally, with my newly prettied command prompt, I
~/documents/legc/src> grep -r -F \”.L .
and found that buried in a header file: /include/llvm/IR/DataLayout.h
were a bunch of hardcoded values including:

  const char *getPrivateGlobalPrefix() const {
    switch (ManglingMode) {
    case MM_None:
      return "";
    case MM_ELF:
      return ".L";         ************* HAH! ******************
    case MM_Mips:
      return "$";
    case MM_MachO:
    case MM_WINCOFF:
      return "L";
    }
    llvm_unreachable("invalid mangling mode");
  }

I can’t believe this is original llvm code but i haven’t tracked it down yet. Anyway, changing that to $$L worked in the short term. Actually, I doubt that the $$L is the right thing to use, I believe that the ‘.’ just means it’s local to the assembly and my $$L labels are more temporary than that. I may need to use something like _$_L and see what happens.

I have been trying to come to grips with the llvm conditional branch to match it in instrinfo.td.
While I was grep’ing,
grep -r br_cc . turned up
./lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp:  case ISD::BR_CC: return “br_cc”;

and looking for ISD::BR_CC, I found – among other things

SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
  switch (Op.getOpcode()) {
  default: llvm_unreachable("Don't know how to custom lower this!");
  case ISD::ConstantPool:  return LowerConstantPool(Op, DAG);
  case ISD::BlockAddress:  return LowerBlockAddress(Op, DAG);
  case ISD::GlobalAddress:
    switch (Subtarget->getTargetTriple().getObjectFormat()) {
    default: llvm_unreachable("unknown object format");
    case Triple::COFF:
      return LowerGlobalAddressWindows(Op, DAG);
    case Triple::ELF:
      return LowerGlobalAddressELF(Op, DAG);
    case Triple::MachO:
      return LowerGlobalAddressDarwin(Op, DAG);
    }
  case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
  case ISD::SELECT:        return LowerSELECT(Op, DAG);
  case ISD::SELECT_CC:     return LowerSELECT_CC(Op, DAG);
  case ISD::BR_CC:         return LowerBR_CC(Op, DAG);
 

Where LEG has

SDValue LEGTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
  switch (Op.getOpcode()) {
  default:
    llvm_unreachable("Unimplemented operand");
  case ISD::GlobalAddress:
    return LowerGlobalAddress(Op, DAG);
  }
}

so somewhere something tells llvm which ops to try lowering. I THINK if I had a pattern that matched the BR_CC that would drive me into LowerOperation – NOPE, because I have one that matches BR and I don’t go in for that.

Mystery!

Ten Thousand Views

I know it’s dumb but wordpress provides detailed stats on visitors and views of your blog.  Since I discovered that i’ve been checking mine regularly and i noticed i was getting close to 10,000 page views – this time it was just over.   It’s usually 10-15 visitors in a day and 30-50 page views.  This gets distorted if there’s something like a post on hack-a-day or similar blogs.  The run of the mill visits are people searching for uses of peripherals like the TMS1638 or the W5500. This blog is mostly about myself keeping track of what i’ve done but i’m happy if anyone finds it interesting or useful and hey – I’m not above showing off!
15-03-28 10k views

Serial Comm on the Macbook – Screen

15-03-27 screen

On windows I have a bajillion choices of serial monitor programs, I use Terminal from Bray Software.

On the mac, the simplest choice seems to be “screen” which is a built-in command line app. To use it, you find your modem name, then invoke screen as follows
bills-MacBook-Pro:~ bill$ ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port /dev/tty.SparkFun-BT-SerialPort
/dev/tty.Bluetooth-Modem /dev/tty.usbserial-FTWUA7K0

bills-MacBook-Pro:~ bill$ screen
Once screen starts it takes over the terminal window and you’re talking to the serial port. One obvious issue is the stair step output which is something to do with line endings in unix.

To get out of Screen you can type ^a ^\. Don’t type ^c because that kills the whole terminal window while leaving screen running detached in the background and the serial port tied up! You can reconnect to the session with screen -r.

Screen has a lot of other options and capabilities I don’t even think it’s primarily a serial comm application.

Double Dabble Forever?

Charles Richmond and I keep poking at the double dabble algorithm for converting from binary to ascii numbers. His latest effort is very nice and well documented. It needs a little work to fit with the compiler but i’m anxious to see how it performs.
Charles’ Explanation of the code

		TITL	"1802 Cross-Assembler Double-Dabble Source"
		EJCT	60

		CPU	1802

NUMBER		EQU	0

;
; Register Definitions:
;
R0		EQU	0
R1		EQU	1
R2		EQU	2
R3		EQU	3
R4		EQU	4
R5		EQU	5
R6		EQU	6
R7		EQU	7
R8		EQU	8
R9		EQU	9
R10		EQU	10
R11		EQU	11
R12		EQU	12
R13		EQU	13
R14		EQU	14
R15		EQU	15

; **********************************
; R6  - BINARY BIT COUNT
; R8 & R9 - BINARY NUMBER
; R12 - INDEX REGISTER
; R13 - LOW BYTE STORES LOCAL LOOP COUNTER
; R13 - HIGH BYTE SAVES CURRENT BCD DIGIT
; R14 - LOW BYTE STORES ACTIVE BCD DIGIT COUNT
; R14 - HIGH BYTE SAVES CARRY VALUE (DF)
; **********************************

BGNDIG:         BYTE    0,0,0,0,0,0,0,0,0
ENDDIG:         BYTE    1

CONVRT:         BYTE    $00,$CE,$ED,$BB         ; DECIMAL 847,291

START		ORG	100H
; -----------------
; *** SET UP INDEX REGISTER LOAD
                LDI     HIGH(ENDDIG)
                PHI     R12
                LDI     LOW(ENDDIG)
                PLO     R5
; -----------------
; *** LOAD BINARY NUMBER TO CONVERT INTO R8 AND R9
                LDI     HIGH(CONVRT)
                PHI     R13
                LDI     LOW(CONVRT)
                PLO     R13
                LDA     R13
                PHI     R8
                LDA     R13
                PLO     R8
                LDA     R13
                PHI     R9
                LDA     R13
                PLO     R9
; -----------------
; *** SET UPPER BYTE OF R6 TO 1
                LDI     1
                PHI     R6              ;STORE CONSTANT 1 INTO HIGH BYTE OF R6
                PLO     R14             ;ACTIVE BCD DIGIT COUNT -- STARTS AT 1
; -----------------
; *** SET BINARY BIT COUNT IN LOW BYTE OF R6
                LDI     32
                PLO     R6
; -----------------
; SHIFT OUT HIGH ORDER ZERO BITS OF BINARY NUMBER
SHFOUT:         GLO     R9
                SHLC
                PLO     R9
;           -----------------
                GHI     R9
                SHLC 
                PHI     R9
;           -----------------
                GLO     R8
                SHLC
                PLO     R8
;           -----------------
                GHI     R8
                SHLC 
                PHI     R8
;           -----------------
                DEC     R6              ;DECREMENT BINARY BIT COUNT
                BNF     SHFOUT
;
;
;
; -----------------
; *** MAIN DOUBLE DABBLE LOOP
NLOOP:
; -----------------
; SHIFT OUT HIGH-ORDER BIT OF BINARY NUMBER
; -----------------
                GLO     R9
                SHLC
                PLO     R9
;           -----------------
                GHI     R9
                SHLC 
                PHI     R9
;           -----------------
                GLO     R8
                SHLC
                PLO     R8
;           -----------------
                GHI     R8
                SHLC 
                PHI     R8
; -----------------
; SET INDEX REGISTER (LOW BYTE ONLY)
                GLO     R5              ;GET INDEX LOW BYTE
                PLO     R12             ;STORE IN INDEX REG.
; -----------------
; CALCULATE LOOP COUNT
                GLO     R14             ;GET ACTIVE BCD DIGIT COUNT
                PLO     R13             ;STORE LOCAL LOOP COUNT
UNILP:
; -----------------
; *** SAVE DF (CARRY) IN UPPER BYTE OF R14
                SHLC                    ;GET CARRY TO LOW-ORDER BIT OF D
                PHI     R14             ;SAVE D IN UPPER BYTE OF R14
; ----------------
; *** TEST ONE BYTE FOR PRE-CORRECTION                
                LDX                     ;LOAD D FROM INDEX ADDRESS
                PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
                SMI     5               ;IS D > 4
                BNF     NOFIX           ;SKIP CORRECTION IF D < 0
; *** PRE-CORRECT BCD DIGIT
                ADI     128             ;ADD 3 CORRECTION + 5 RESTORE + 120
                PHI     R13             ;SAVE BCD DIGIT IN UPPER BYTE OF R13
NOFIX:
; -----------------
; SHIFT ONE BCD DIGIT
; -----------------
                GHI     R14             ;GET CARRY BACK TO D
                SHR                     ;PUT CARRY VALUE INTO DF
                GHI     R13             ;GET WORKING BCD DIGIT
                SHLC                    ;ROTATE D THROUGH CARRY
                STXD                    ;STORE D AND DECREMENT INDEX REGISTER
; -----------------
; *** UNILP COUNTER OVERHEAD
                DEC     R13             ;DECREMENT CORRECT-SIFT LOOP COUNTER
                GLO     R13             ;D = LOCAL LOOP COUNT
                BNZ     UNILP           ;LOOP UNTIL DONE
; -----------------
; *** IF DF = 1, CREATE NEW BCD DIGIT = 1 -- INCREMENT ACTIVE BCD DIGIT COUNT
                BNF     SKPDIG          ;IF CARRY IS ZERO, NO NEW BCD DIGIT
                INC     R14             ;INCREMENT ACTIVE BCD DIGIT COUNT
                GHI     R6              ;GET A BYTE WITH VALUE OF 1
                STXD                    ;STORE D IN NEW BCD DIGIT POSITION
; -----------------
; *** MAIN LOOP COUNTER OVERHEAD
SKPDIG:         DEC     R6              ;DECREMENT MASTER LOOP COUNTER
                GLO     R6              ;D = BINARY BIT COUNT
                BNZ     NLOOP           ;LOOP UNTIL DONE
                IDL
                END

Programming the 1802 From the Macbook II

I’m back working with the Mac. I have lcc1802 and the assembler working and even avrdude. I’m using Atom for an editor but it doesn’t seem to have hooks for executing the compiler and loader so i’m using a separate shell and some crude shell scripts.

I set up a directory called /usr/local/sh and put in scripts to run the lcc1802 compiler, the asw assembler, and avrdude.

/Users/bill/Documents/lcc/lcc1802/lcc42/build/cpp -I/Users/bill/Documents/lcc/lcc1802/include $1.c | /Users/bill/Documents/lcc/lcc1802/lcc42/build/rcc -target=xr18DH >$1.s
~/Documents/asl-current/asl -q -cpu 1802 -i ~/Documents/lcc/lcc1802/include $1.s &&~/Documents/asl-current/p2hex $1.p $1.hex>p2hex.log
avrdude -u -V -D -patmega644p -cstk500v1 -b57600 -P/dev/cu.usbserial-FTWUA7K0 -U flash:w:$1.hex

Apparently the tradition on a mac is to put scripts in /usr/local/bin but there’s already a lot of stuff in there and this way if i forget what one of my cryptic shells does or is called, it’s easier to find it. I added my directory to the $PATH system variable with
echo ‘PATH=$PATH:/usr/local/sh’ >> ~/.bash_profile
which I got from here (which is also where i found out how to get avrdude)

My Xcode Lesson For the Day

I’m an Xcode beginner and I didn’t realize you couldn’t just move an Xcode project.  I had consolidated and organized my Xcode llvm directories (all 25GB of them) and when i went back to legc it opened ok but wouldn’t show individual files, everything said “no editor”.  I gradually noticed that the files were all highlighted in red indicating it couldn’t find them.  I put the folder back where it had been ad bingo, all was forgiven.

Thus endeth today’s lesson.

Wow – This is Why I Want an LLVM Compiler!

A while ago I found an LLVM implementation for the Z80.  I downloaded and built it and ran a few examples.  Later, someone asked whether it actually supported C++.  I figured it would but hadn’t tried it so today i did with delightful results.

This example has two different definitions of the function foo(). The first one takes two arguments and returns the sum. The second takes a single argument and returns it as its value. The main procedure calls foo(1,2) so it should invoke the first foo().

short int foo(short int a, short int b) {
    short int result = a + b;   // r0 + r1
    return result;        // r0
}
short int foo(int a) {
    int result = a;   // r0
    return result;        // r0
}

int main(){
  return foo(1,2);
}

I was looking to see that i didn’t get a double definition error and what the mechanism for distinguishing was.

	.file	"exwjr1.cpp"
	.text
	.globl	_Z3fooss
	.type	_Z3fooss,@function
_Z3fooss:
	push	ix
	push	bc
	ld	ix, 0
	add	ix, sp
	ld	sp, ix
	ld	b, h
	ld	c, l
	ld	l, (ix+6)
	ld	h, (ix+7)
	add	hl, bc
	pop	bc
	pop	ix
	ret
.tmp0:
	.size	_Z3fooss, .tmp0-_Z3fooss

	.globl	_Z3fooi
	.type	_Z3fooi,@function
_Z3fooi:
	ret
.tmp1:
	.size	_Z3fooi, .tmp1-_Z3fooi

	.globl	main
	.type	main,@function
main:
	ld	hl, 3
	ret
.tmp2:
	.size	main, .tmp2-main

In fact, I did not get an error, and the way of distinguishing my two foo’s was by tacking the argument types onto the name, so C++ is clearly supported. Two things really impressed me though.

  1. The second foo variant just returns it’s first argument – Clang generated only a “ret” since the argument was already in HL which is also the return value register.
  2. My call to foo from main had constant arguments so Clang looked at the code being called and just calculated the result as a constant at compile time. This is nothing short of splendid!

I’m not at all sure what the Z80 code in the first foo is doing but i assume it’s at least correct if not optimal.

Follow

Get every new post delivered to your Inbox.